public void Minimal_notice_generates_valid_XML()
        {
            var notice = new AirbrakeNotice();
            notice.ApiKey = "123456";
            notice.Error = new AirbrakeError
                               {
                                   Class = "TestError",
                                   Message = "something blew up",
                                   Backtrace = new[]
                                                   {
                                                       new AirbrakeTraceLine ("unknown.cs", 0) { Method = "unknown"}
                                                   }
                               };
            notice.Notifier = new AirbrakeNotifier
                                  {
                                      Name = "hopsharp",
                                      Version = "2.0",
                                      Url = "http://github.com/krobertson/hopsharp"
                                  };
            notice.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);
            }
        }
        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);
        }
    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();
    }
        private void AddContextualInformation(AirbrakeNotice notice, MethodBase catchingMethod, Dictionary<string, string> info = null)
        {
            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));
                }
            }

            if (info != null)
            {
                foreach (var item in info)
                {
                    if (item.Key.ToLower().StartsWith("environment"))
                    {
                        cgiData.Add(new AirbrakeVar(item.Key, item.Value));
                    }
                    else if (item.Key.ToLower().StartsWith("session"))
                    {
                        session.Add(new AirbrakeVar(item.Key, item.Value));
                    }
                    else
                    {
                        parameters.Add(new AirbrakeVar(item.Key, item.Value));
                    }
                }
            }

            request.CgiData = cgiData.ToArray();
            request.Params = parameters.Any() ? parameters.ToArray() : null;
            request.Session = session.Any() ? session.ToArray() : null;
            notice.Request = request;
        }
        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>();

            request.CgiData = cgiData.ToArray();
            request.Params = parameters.Any() ? parameters.ToArray() : null;
            request.Session = session.Any() ? session.ToArray() : null;
            notice.Request = request;
        }
        private static void AddInfoFromHttpContext(AirbrakeNotice notice, MethodBase catchingMethod)
        {
            HttpContext httpContext = HttpContext.Current;

            if (httpContext == null)
                return;

            HttpRequest request = httpContext.Request;

            string component = String.Empty;
            string action = String.Empty;

            if (catchingMethod != null)
            {
                action = catchingMethod.Name;

                if (catchingMethod.DeclaringType != null)
                    component = catchingMethod.DeclaringType.FullName;
            }

            notice.Request = new AirbrakeRequest(request.Url, component)
            {
                Action = action,
                CgiData = BuildVars(request.Headers).ToArray(),
                Params = BuildVars(request.Params).ToArray(),
                Session = BuildVars(httpContext.Session).ToArray(),
            };
        }
        /// <summary>
        /// Creates a <see cref="AirbrakeNotice"/> from the the specified error.
        /// </summary>
        /// <param name="error">The error.</param>
        /// <param name="info"> Additional info to send to Airbrake.</param>
        /// <returns></returns>
        public AirbrakeNotice Notice(AirbrakeError error, Dictionary<string, string> info = null)
        {
            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, info);

            return notice;
        }
        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);
        }
        /// <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;

            AddInfoFromHttpContext(notice, catchingMethod);

            return notice;
        }
        /// <summary>
        /// Creates a <see cref="AirbrakeNotice"/> from the the specified error.
        /// </summary>
        /// <param name="error">The error.</param>
        /// <returns></returns>
        public AirbrakeNotice BuildNotice(AirbrakeError error)
        {
            _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 Notice_missing_error_fails_validation()
        {
            var notice = new AirbrakeNotice
            {
                ApiKey = "123456",
                Request = new AirbrakeRequest(new Uri("http://example.com/"), GetType().FullName)
                {
                    Action = "Maximal_notice_generates_valid_XML",
                },
                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);

            TestDelegate throwing = () => AirbrakeValidator.ValidateSchema(xml);
            XmlSchemaValidationException exception = Assert.Throws<XmlSchemaValidationException>(throwing);

            Console.WriteLine(exception);

            Assert.That(exception.Message, Is.StringContaining("notice"));
            Assert.That(exception.Message, Is.StringContaining("error"));
            Assert.That(exception.LineNumber, Is.EqualTo(18));
            Assert.That(exception.LinePosition, Is.EqualTo(3));
        }
        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>
        /// 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,
            };

            if (HttpContext.Current != null)
            {
                Assembly assembly = Assembly.GetExecutingAssembly();

                notice.Request = new AirbrakeRequest(HttpContext.Current.Request.Url, assembly.CodeBase)
                {
                    Params = BuildParams().ToArray(),
                    Session = BuildSession().ToArray(),
                    CgiData = BuildCgiData().ToArray(),
                };
            }

            return notice;
        }
        public void MinimalNoticeGeneratesValidXml()
        {
            var error = new AirbrakeError
            {
                Class   = "TestError",
                Message = "something blew up",

                Backtrace = new[]
                {
                    new AirbrakeTraceLine("unknown.cs", 0)
                    {
                        Method = "unknown"
                    }
                }
            };

            var notice = new AirbrakeNotice
            {
                ApiKey = "123456",
                Error  = error,

                Notifier = new AirbrakeNotifier
                {
                    Name    = "sharpbrake",
                    Version = "2.2.2.0",
                    Url     = "https://github.com/airbrake/SharpBrake"
                },

                ServerEnvironment = new AirbrakeServerEnvironment("staging")
                {
                    ProjectRoot = "/test",
                },
            };

            var serializer = new CleanXmlSerializer<AirbrakeNotice>();
            var xml        = serializer.ToXml(notice);

            AirbrakeValidator.ValidateSchema(xml);
        }
        public void NoticeMissingErrorFailsValidation()
        {
            var notice = new AirbrakeNotice
            {
                ApiKey = "123456",

                Request = new AirbrakeRequest(new Uri("http://example.com/"), GetType().FullName)
                {
                    Action = "NoticeMissingErrorFailsValidation",
                },

                Notifier = new AirbrakeNotifier
                {
                    Name    = "sharpbrake",
                    Version = "2.2.2.0",
                    Url     = "https://github.com/airbrake/SharpBrake"
                },

                ServerEnvironment = new AirbrakeServerEnvironment("staging")
                {
                    ProjectRoot = "/test",
                },
            };

            var serializer = new CleanXmlSerializer<AirbrakeNotice>();
            var xml       = serializer.ToXml(notice);

            TestDelegate throwing = () => AirbrakeValidator.ValidateSchema(xml);

            var exception = Assert.Throws<XmlSchemaValidationException>(throwing);

            Console.WriteLine(exception);

            Assert.That(exception.Message, Is.StringContaining("notice"));
            Assert.That(exception.Message, Is.StringContaining("error"));
        }
 public void Send(AirbrakeNotice notice)
 {
   this.Client.Send(notice);
 }
        /// <summary>
        /// Creates a <see cref="AirbrakeNotice"/> from the the specified error.
        /// </summary>
        /// <param name="error">The error.</param>
        /// <param name="extraParams">extra data for adding the params in airbrake notice </param>
        /// <returns></returns>
        public AirbrakeNotice Notice(AirbrakeError error, IEnumerable<KeyValuePair<string, string>> extraParams = null)
        {
            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, extraParams);

            return notice;
        }