/// <summary> Notice an error identified by an exception report it to the New Relic service. If
        /// this method is called within a transaction, the exception will be reported with the
        /// transaction when it finishes. If it is invoked outside of a transaction, a traced error will
        /// be created and reported to the New Relic service. Only the exception/parameter pair for the
        /// first call to NoticeError during the course of a transaction is retained. Supports web
        /// applications only. </summary>
        ///
        /// <exception cref="ArgumentNullException"> Thrown when <paramref name="exception"/> is null. </exception>
        ///
        /// <param name="exception">	    The exception to be reported. Only part of the exception's
        /// information may be retained to prevent the report from being too large. </param>
        /// <param name="customAttributes"> Custom parameters to include in the traced error. May be
        /// null. Only 10,000 characters of combined key/value data is retained. </param>
        public void NoticeError(Exception exception, IDictionary <string, string> customAttributes)
        {
            exception = exception ?? throw new ArgumentNullException(nameof(exception));

            using (new IgnoreWork())
            {
                var transaction = TryGetCurrentInternalTransaction();
                if (IsCustomExceptionIgnored(exception, transaction))
                {
                    return;
                }
                var errorData = _errorService.FromException(exception, customAttributes);
                ProcessNoticedError(errorData, transaction);
            }
        }
        public void GetErrorEvent_NoTransaction_WithException_ContainsCorrectAttributes()
        {
            // Arrange
            var customAttributes = new AttributeValueCollection(AttributeDestinations.ErrorEvent);

            _attribDefs.GetCustomAttributeForError("custom attribute name").TrySetValue(customAttributes, "custom attribute value");
            var errorData = _errorService.FromException(new NullReferenceException("NRE message"));

            // Act
            float priority   = 0.5f;
            var   errorEvent = _errorEventMaker.GetErrorEvent(errorData, customAttributes, priority);

            var agentAttributes     = errorEvent.AgentAttributes().Keys.ToArray();
            var intrinsicAttributes = errorEvent.IntrinsicAttributes().Keys.ToArray();
            var userAttributes      = errorEvent.UserAttributes().Keys.ToArray();

            // Assert
            NrAssert.Multiple(
                () => Assert.AreEqual(false, errorEvent.IsSynthetics),
                () => Assert.AreEqual(0, agentAttributes.Length),
                () => Assert.AreEqual(4, intrinsicAttributes.Length),
                () => Assert.AreEqual(1, userAttributes.Length),

                () => Assert.Contains("error.class", intrinsicAttributes),
                () => Assert.Contains("error.message", intrinsicAttributes),
                () => Assert.Contains("timestamp", intrinsicAttributes),
                () => Assert.Contains("type", intrinsicAttributes),

                () => Assert.Contains("custom attribute name", userAttributes)
                );
        }
        public void FromException_ReturnsExpectedErrorData(bool stripExceptionMessages)
        {
            SetupConfiguration(_exceptionsToIgnore, null, null, _statusCodesToIgnore, stripExceptionMessages, null, null, null, true);

            var exception = new Exception();
            var errorData = _errorService.FromException(exception);

            if (!stripExceptionMessages)
            {
                Assert.AreEqual(exception.Message, errorData.ErrorMessage);
                Assert.IsNotNull(errorData.StackTrace);
            }
            else
            {
                Assert.AreEqual(ErrorData.StripExceptionMessagesMessage, errorData.ErrorMessage);
                Assert.IsTrue(errorData.StackTrace.Contains(ErrorData.StripExceptionMessagesMessage));
            }

            Assert.AreEqual(exception.GetType().FullName, errorData.ErrorTypeName);
            Assert.AreEqual(DateTimeKind.Utc, errorData.NoticedAt.Kind);
            Assert.IsNull(errorData.Path);
            Assert.IsEmpty(errorData.CustomAttributes);
        }