protected override void OnLoad(EventArgs e) { // // Retrieve the ID of the error to display and read it from // the store. // string errorId = StringEtc.MaskNull(this.Request.QueryString["id"]); if (errorId.Length == 0) return; _errorEntry = this.ErrorLog.GetError(errorId); // // Perhaps the error has been deleted from the store? Whatever // the reason, bail out silently. // if (_errorEntry == null) return; // // Setup the title of the page. // this.Title = string.Format("Error: {0} [{1}]", _errorEntry.Error.Type, _errorEntry.Id); base.OnLoad(e); }
public void Add(Guid id, ErrorLogEntry entry) { Debug.Assert(entry != null); Debug.AssertStringNotEmpty(entry.Id); Debug.Assert(this.Count <= _size); if (this.Count == _size) { BaseRemoveAt(0); } BaseAdd(entry.Id, entry); }
protected override void Render(HtmlTextWriter writer) { if (writer == null) { throw new ArgumentNullException("writer"); } // // Retrieve the ID of the error to display and read it from // the log. // string errorId = StringEtc.MaskNull(this.Request.QueryString["id"]); if (errorId.Length == 0) { return; } ErrorLogEntry errorEntry = this.ErrorLog.GetError(errorId); if (errorEntry == null) { return; } // // If we have a host (ASP.NET) formatted HTML message // for the error then just stream it out as our response. // if (errorEntry.Error.WebHostHtmlMessage.Length != 0) { writer.Write(errorEntry.Error.WebHostHtmlMessage); } }
/// <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, IList errorEntryList) { if (pageIndex < 0) { throw new ArgumentOutOfRangeException("pageIndex"); } if (pageSize < 0) { throw new ArgumentOutOfRangeException("pageSite"); } // // 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; int totalCount; _lock.AcquireReaderLock(Timeout.Infinite); try { if (_entries == null) { return(0); } int lastIndex = Math.Max(0, _entries.Count - (pageIndex * pageSize)) - 1; selectedEntries = new ErrorLogEntry[lastIndex + 1]; int sourceIndex = lastIndex; int targetIndex = 0; while (sourceIndex >= 0) { selectedEntries[targetIndex++] = _entries[sourceIndex--]; } totalCount = _entries.Count; } finally { _lock.ReleaseReaderLock(); } // // Return copies of fetched entries. If the Error class would // be immutable then this step wouldn't be necessary. // foreach (ErrorLogEntry entry in selectedEntries) { Error error = (Error)((ICloneable)entry.Error).Clone(); errorEntryList.Add(new ErrorLogEntry(this, entry.Id, error)); } return(totalCount); }
private void RenderErrors(HtmlTextWriter writer) { Debug.Assert(writer != null); // // Create a table to display error information in each row. // Table table = new Table(); table.ID = "ErrorLog"; table.CellSpacing = 0; // // Create the table row for headings. // TableRow headRow = new TableRow(); headRow.Cells.Add(FormatCell(new TableHeaderCell(), "Host", "host-col")); headRow.Cells.Add(FormatCell(new TableHeaderCell(), "Code", "code-col")); headRow.Cells.Add(FormatCell(new TableHeaderCell(), "Type", "type-col")); headRow.Cells.Add(FormatCell(new TableHeaderCell(), "Error", "error-col")); headRow.Cells.Add(FormatCell(new TableHeaderCell(), "User", "user-col")); headRow.Cells.Add(FormatCell(new TableHeaderCell(), "Date", "date-col")); headRow.Cells.Add(FormatCell(new TableHeaderCell(), "Time", "time-col")); table.Rows.Add(headRow); // // Generate a table body row for each error. // for (int errorIndex = 0; errorIndex < _errorEntryList.Count; errorIndex++) { ErrorLogEntry errorEntry = (ErrorLogEntry)_errorEntryList[errorIndex]; Error error = errorEntry.Error; TableRow bodyRow = new TableRow(); bodyRow.CssClass = errorIndex % 2 == 0 ? "even-row" : "odd-row"; // // Format host and status code cells. // bodyRow.Cells.Add(FormatCell(new TableCell(), error.HostName, "host-col")); bodyRow.Cells.Add(FormatCell(new TableCell(), error.StatusCode.ToString(), "code-col")); bodyRow.Cells.Add(FormatCell(new TableCell(), GetSimpleErrorType(error), "type-col", error.Type)); // // Format the message cell, which contains the message // text and a details link pointing to the page where // all error details can be viewed. // TableCell messageCell = new TableCell(); messageCell.CssClass = "error-col"; Label messageLabel = new Label(); messageLabel.Text = this.Server.HtmlEncode(error.Message); HyperLink detailsLink = new HyperLink(); detailsLink.NavigateUrl = this.Request.Path + "/detail?id=" + errorEntry.Id; detailsLink.Text = "[Details]"; messageCell.Controls.Add(messageLabel); messageCell.Controls.Add(new LiteralControl(" ")); messageCell.Controls.Add(detailsLink); bodyRow.Cells.Add(messageCell); // // Format the user, date and time cells. // bodyRow.Cells.Add(FormatCell(new TableCell(), error.User, "user-col")); bodyRow.Cells.Add(FormatCell(new TableCell(), error.Time.ToShortDateString(), "date-col", error.Time.ToLongDateString())); bodyRow.Cells.Add(FormatCell(new TableCell(), error.Time.ToLongTimeString(), "time-col")); // // Finally, add the row to the table. // table.Rows.Add(bodyRow); } table.RenderControl(writer); }
/// <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 void Log(Error error) { if (error == null) throw new ArgumentNullException("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) ((ICloneable) error).Clone(); error.ApplicationName = this.ApplicationName; Guid newId = Guid.NewGuid(); ErrorLogEntry entry = new ErrorLogEntry(this, newId.ToString(), error); _lock.AcquireWriterLock(Timeout.Infinite); try { if (_entries == null) { _entries = new EntryCollection(_size); } _entries.Add(newId, entry); } finally { _lock.ReleaseWriterLock(); } }
/// <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, IList errorEntryList) { if (pageIndex < 0) throw new ArgumentOutOfRangeException("pageIndex"); if (pageSize < 0) throw new ArgumentOutOfRangeException("pageSite"); // // 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; int totalCount; _lock.AcquireReaderLock(Timeout.Infinite); try { if (_entries == null) { return 0; } int lastIndex = Math.Max(0, _entries.Count - (pageIndex * pageSize)) - 1; selectedEntries = new ErrorLogEntry[lastIndex + 1]; int sourceIndex = lastIndex; int targetIndex = 0; while (sourceIndex >= 0) { selectedEntries[targetIndex++] = _entries[sourceIndex--]; } totalCount = _entries.Count; } finally { _lock.ReleaseReaderLock(); } // // Return copies of fetched entries. If the Error class would // be immutable then this step wouldn't be necessary. // foreach (ErrorLogEntry entry in selectedEntries) { Error error = (Error) ((ICloneable) entry.Error).Clone(); errorEntryList.Add(new ErrorLogEntry(this, entry.Id, error)); } return totalCount; }
public void ProcessRequest(HttpContext context) { context.Response.ContentType = "text/xml"; // // Get the last set of errors for this application. // const int pageSize = 15; ArrayList errorEntryList = new ArrayList(pageSize); ErrorLog.Default.GetErrors(0, pageSize, errorEntryList); // // We'll be emitting RSS vesion 0.91. // RichSiteSummary rss = new RichSiteSummary(); rss.version = "0.91"; // // Set up the RSS channel. // Channel channel = new Channel(); channel.title = "Error log of " + ErrorLog.Default.ApplicationName + " on " + Environment.MachineName; channel.description = "Log of recent errors"; channel.language = "en"; channel.link = context.Request.Url.GetLeftPart(UriPartial.Authority) + context.Request.ServerVariables["URL"]; rss.channel = channel; // // For each error, build a simple channel item. Only the title, // description, link and pubDate fields are populated. // channel.item = new Item[errorEntryList.Count]; for (int index = 0; index < errorEntryList.Count; index++) { ErrorLogEntry errorEntry = (ErrorLogEntry)errorEntryList[index]; Error error = errorEntry.Error; Item item = new Item(); item.title = error.Message; item.description = "An error of type " + error.Type + " occurred. " + error.Message; item.link = channel.link + "/detail?id=" + errorEntry.Id; item.pubDate = error.Time.ToUniversalTime().ToString("r"); channel.item[index] = item; } // // Stream out the RSS XML. // XmlSerializer serializer = new XmlSerializer(typeof(RichSiteSummary)); serializer.Serialize(context.Response.Output, rss); }