/// <summary> /// Sends the specified exception to Airbrake. /// </summary> /// <param name="exception">The e.</param> public void Send(Exception exception) { AirbrakeNotice notice = this.builder.Notice(exception); //TODO: set up request, session and server headers // Why would that be necessary, it's set in Send(AirbrakeNotice), isn't it? - @asbjornu // Send the notice Send(notice); }
public void Notice_contains_ServerEnvironment_and_Notifier() { AirbrakeNotice notice = this.builder.Notice((AirbrakeError)null); Assert.That(notice.ServerEnvironment, Is.Not.Null); Assert.That(notice.ServerEnvironment.ProjectRoot, Is.Not.Null); Assert.That(notice.ServerEnvironment.EnvironmentName, Is.Not.Null); Assert.That(notice.Notifier, Is.Not.Null); Assert.That(notice.ApiKey, Is.Not.Empty); Assert.That(notice.Version, Is.Not.Null); }
public void Maximal_notice_generates_valid_XML() { var error = Activator.CreateInstance <AirbrakeError>(); error.Class = "TestError"; error.Message = "something blew up"; error.Backtrace = new[] { new AirbrakeTraceLine("unknown.cs", 0) { Method = "unknown" } }; var notice = new AirbrakeNotice { ApiKey = "123456", Error = error, Request = new AirbrakeRequest(new Uri("http://example.com/"), GetType().FullName) { Action = "Maximal_notice_generates_valid_XML", Component = "MyApp.HomeController", CgiData = new[] { new AirbrakeVar("REQUEST_METHOD", "POST"), }, Params = new[] { new AirbrakeVar("Form.Key1", "Form.Value1"), }, Session = new[] { new AirbrakeVar("UserId", "1"), }, Url = "http://example.com/myapp", }, Notifier = new AirbrakeNotifier { Name = "sharpbrake", Version = "2.2", Url = "http://github.com/asbjornu/SharpBrake", }, ServerEnvironment = new AirbrakeServerEnvironment("staging") { ProjectRoot = "/test", }, }; var serializer = new CleanXmlSerializer <AirbrakeNotice>(); string xml = serializer.ToXml(notice); AirbrakeValidator.ValidateSchema(xml); }
/// <summary> /// Sends the specified notice to Airbrake. /// </summary> /// <param name="notice">The notice.</param> public void Send(AirbrakeNotice notice) { InternalLogger.Debug("{0}.Send({1})", GetType(), notice); try { // If no API key, get it from the appSettings if (String.IsNullOrEmpty(notice.ApiKey)) { // If none is set, just return... throwing an exception is pointless, since one was already thrown! if (String.IsNullOrEmpty(ConfigurationManager.AppSettings["Airbrake.ApiKey"])) { InternalLogger.Fatal("No 'Airbrake.ApiKey' found. Please define one in AppSettings."); return; } notice.ApiKey = this.builder.Configuration.ApiKey; } // Create the web request var request = WebRequest.Create(this.configuration.ServerUri) as HttpWebRequest; if (request == null) { InternalLogger.Fatal("Couldn't create a request to '{0}'.", this.configuration.ServerUri); return; } // Set the basic headers request.ContentType = "text/xml"; request.Accept = "text/xml"; request.KeepAlive = false; // It is important to set the method late... .NET quirk, it will interfere with headers set after request.Method = "POST"; InternalLogger.Debug("Sending Airbrake notice to {0} with key {1}, env: {2}", this.configuration.ServerUri, this.configuration.ApiKey, this.configuration.EnvironmentName); // Go populate the body SetRequestBody(request, notice); // Begin the request, yay async request.BeginGetResponse(RequestCallback, request); } catch (Exception ex) { InternalLogger.Fatal("An error occurred while trying to send to Airbrake: {0}", ex.Message); } }
private void SetRequestBody(WebRequest request, AirbrakeNotice notice) { var serializer = new CleanXmlSerializer <AirbrakeNotice>(); string xml = serializer.ToXml(notice); this.log.Debug(f => f("Sending the following to '{0}':\n{1}", request.RequestUri, xml)); byte[] payload = Encoding.UTF8.GetBytes(xml); request.ContentLength = payload.Length; using (Stream stream = request.GetRequestStream()) { stream.Write(payload, 0, payload.Length); } }
/// <summary> /// Writes logging event to the log target. /// </summary> /// <param name="logEvent">Logging event to be written out.</param> protected override void Write(LogEventInfo logEvent) { if (logEvent.Exception != null) { AirbrakeNotice notice = this.SharpbrakeClient.BuildNotice(logEvent.Exception); // Override the notice message so we have the full exception // message, including the messages of the inner exceptions. // Also, include the log message, if it is set. string exceptionMessage = BuildExceptionMessage(logEvent.Exception); notice.Error.Message = !string.IsNullOrEmpty(logEvent.Message) ? logEvent.Message + " " + exceptionMessage : exceptionMessage; this.SharpbrakeClient.Send(notice); } }
public void Send_EndRequestEventIsInvoked_And_ResponseOnlyContainsApiError() { bool requestEndInvoked = false; AirbrakeResponseError[] errors = null; int i = 0; this.client.RequestEnd += (sender, e) => { requestEndInvoked = true; errors = e.Response.Errors; }; var configuration = new AirbrakeConfiguration { ApiKey = Guid.NewGuid().ToString("N"), EnvironmentName = "test", }; var builder = new AirbrakeNoticeBuilder(configuration); AirbrakeNotice notice = builder.Notice(new Exception("Test")); notice.Request = new AirbrakeRequest("http://example.com", "Test") { Params = new[] { new AirbrakeVar("TestKey", "TestValue") } }; this.client.Send(notice); while (!requestEndInvoked) { // Sleep for maximum 5 seconds to wait for the request to end. Can probably be done more elegantly. if (i++ == 50) { break; } Thread.Sleep(100); } Assert.That(requestEndInvoked, Is.True); Assert.That(errors, Is.Not.Null); Assert.That(errors, Has.Length.EqualTo(1)); }
/// <summary> /// Creates a <see cref="AirbrakeNotice"/> from the the specified exception. /// </summary> /// <param name="exception">The exception.</param> /// <returns> /// A <see cref="AirbrakeNotice"/>, created from the the specified exception. /// </returns> public AirbrakeNotice Notice(Exception exception) { if (exception == null) { throw new ArgumentNullException("exception"); } this.log.Debug(f => f("{0}.Notice({1})", GetType(), exception.GetType()), exception); var notice = new AirbrakeNotice { ApiKey = Configuration.ApiKey, Error = ErrorFromException(exception), Notifier = Notifier, ServerEnvironment = ServerEnvironment, }; return(notice); }
/// <summary> /// Creates a <see cref="AirbrakeNotice"/> from the the specified error. /// </summary> /// <param name="error">The error.</param> /// <returns></returns> public AirbrakeNotice Notice(AirbrakeError error) { this.log.Debug(f => f("{0}.Notice({1})", GetType(), error)); var notice = new AirbrakeNotice { ApiKey = Configuration.ApiKey, Error = error, Notifier = Notifier, ServerEnvironment = ServerEnvironment, }; MethodBase catchingMethod = (error != null) ? error.CatchingMethod : null; AddContextualInformation(notice, catchingMethod); return(notice); }
public void LogEvent_WithExecption_CallsClient() { var client = A.Fake <ISharpbrakeClient>(); Exception ex = new ApplicationException("something bad happened"); // using activator to avoid the obsolete tag on the constructor. AirbrakeError error = Activator.CreateInstance <AirbrakeError>(); AirbrakeNotice notice = new AirbrakeNotice() { Error = error }; A.CallTo(() => client.BuildNotice(ex)).Returns(notice); AirBrakeTarget target = new AirBrakeTarget(client); NLog.Config.SimpleConfigurator.ConfigureForTargetLogging(target); logger.InfoException("kaboom", ex); A.CallTo(() => client.Send(notice)).MustHaveHappened(); }
public void Minimal_notice_with_request_generates_valid_XML() { var error = Activator.CreateInstance <AirbrakeError>(); error.Class = "TestError"; error.Message = "something blew up"; error.Backtrace = new[] { new AirbrakeTraceLine("unknown.cs", 0) { Method = "unknown" } }; var notice = new AirbrakeNotice { ApiKey = "123456", Error = error, Request = new AirbrakeRequest(new Uri("http://example.com/"), GetType().FullName) { Session = new AirbrakeVar[0] }, Notifier = new AirbrakeNotifier { Name = "sharpbrake", Version = "2.2", Url = "http://github.com/asbjornu/SharpBrake" }, ServerEnvironment = new AirbrakeServerEnvironment("staging") { ProjectRoot = "/test", }, }; var serializer = new CleanXmlSerializer <AirbrakeNotice>(); string xml = serializer.ToXml(notice); AirbrakeValidator.ValidateSchema(xml); }
public void Send_EndRequestEventIsInvoked_And_ResponseOnlyContainsApiError() { bool requestEndInvoked = false; AirbrakeResponseError[] errors = null; int i = 0; this.client.RequestEnd += (sender, e) => { requestEndInvoked = true; errors = e.Response.Errors; }; var configuration = new AirbrakeConfiguration { ApiKey = Guid.NewGuid().ToString("N"), EnvironmentName = "test", }; var builder = new AirbrakeNoticeBuilder(configuration); AirbrakeNotice notice = builder.Notice(new Exception("Test")); notice.Request = new AirbrakeRequest("http://example.com", "Test") { Params = new[] { new AirbrakeVar("TestKey", "TestValue") } }; this.client.Send(notice); Assert.That(requestEndInvoked, Is.True.After(5000)); Assert.That(errors, Is.Not.Null); Assert.That(errors, Has.Length.EqualTo(1)); }
public void Send(AirbrakeNotice notice) { this.Client.Send(notice); }
private void AddContextualInformation(AirbrakeNotice notice, MethodBase catchingMethod) { var component = String.Empty; var action = String.Empty; if ((notice.Error != null) && (notice.Error.Backtrace != null) && notice.Error.Backtrace.Any()) { // TODO: We should perhaps check whether the topmost back trace is in fact a Controller+Action by performing some sort of heuristic (searching for "Controller" etc.). @asbjornu var backtrace = notice.Error.Backtrace.First(); action = backtrace.Method; component = backtrace.File; } else if (catchingMethod != null) { action = catchingMethod.Name; if (catchingMethod.DeclaringType != null) { component = catchingMethod.DeclaringType.FullName; } } var request = new AirbrakeRequest("http://example.com/", component) { Action = action }; var cgiData = new List <AirbrakeVar> { new AirbrakeVar("Environment.MachineName", Environment.MachineName), new AirbrakeVar("Environment.OSversion", Environment.OSVersion), new AirbrakeVar("Environment.Version", Environment.Version) }; var parameters = new List <AirbrakeVar>(); var session = new List <AirbrakeVar>(); var httpContext = HttpContext.Current; if (httpContext != null) { var httpRequest = httpContext.Request; request.Url = httpRequest.Url.ToString(); cgiData.AddRange(BuildVars(httpRequest.Headers)); cgiData.AddRange(BuildVars(httpRequest.Cookies)); parameters.AddRange(BuildVars(httpRequest.Params)); session.AddRange(BuildVars(httpContext.Session)); if (httpContext.User != null) { cgiData.Add(new AirbrakeVar("User.Identity.Name", httpContext.User.Identity.Name)); } var browser = httpRequest.Browser; if (browser != null) { cgiData.Add(new AirbrakeVar("Browser.Browser", browser.Browser)); cgiData.Add(new AirbrakeVar("Browser.ClrVersion", browser.ClrVersion)); cgiData.Add(new AirbrakeVar("Browser.Cookies", browser.Cookies)); cgiData.Add(new AirbrakeVar("Browser.Crawler", browser.Crawler)); cgiData.Add(new AirbrakeVar("Browser.EcmaScriptVersion", browser.EcmaScriptVersion)); cgiData.Add(new AirbrakeVar("Browser.JavaApplets", browser.JavaApplets)); cgiData.Add(new AirbrakeVar("Browser.MajorVersion", browser.MajorVersion)); cgiData.Add(new AirbrakeVar("Browser.MinorVersion", browser.MinorVersion)); cgiData.Add(new AirbrakeVar("Browser.Platform", browser.Platform)); cgiData.Add(new AirbrakeVar("Browser.W3CDomVersion", browser.W3CDomVersion)); } } request.CgiData = cgiData.ToArray(); request.Params = parameters.Any() ? parameters.ToArray() : null; request.Session = session.Any() ? session.ToArray() : null; notice.Request = request; }
public void Send(AirbrakeNotice notice) { SharpBreak.AirbrakeNotice actualNotice = AirbreakNoticeMap.Map[notice]; _airbrakeClient.Send(actualNotice); }