public void TrackErrorWithObfuscateUserName()
        {
            // Prepared data.
            Constants.UserName = "******";
            var semaphore = new SemaphoreSlim(0);
            var stacktraceWithUserName = $"C:\\{Constants.UserName}\\some\\path;\nC:\\test\\{Constants.UserName}\\some\\path;\nC:\\no.username\\some\\path;";
            var expectedStacktrace     = $"C:\\USER\\some\\path;\nC:\\test\\USER\\some\\path;\nC:\\no.username\\some\\path;";
            var mockException          = new Mock <System.Exception>();

            mockException.Setup(exception => exception.StackTrace).Returns(stacktraceWithUserName);
            mockException.Setup(exception => exception.Message).Returns("Some error message");

            // Mock method.
            HandledErrorLog actualLog = null;

            Mock.Get(_mockNetworkAdapter).Setup(adapter => adapter.SendAsync(
                                                    It.IsAny <string>(),
                                                    It.IsAny <string>(),
                                                    It.IsAny <IDictionary <string, string> >(),
                                                    It.IsAny <string>(),
                                                    It.IsAny <CancellationToken>()))
            .Callback((string uri, string method, IDictionary <string, string> headers, string content, CancellationToken cancellation) =>
            {
                actualLog = JsonConvert.DeserializeObject <LogContainer>(content, LogSerializer.SerializationSettings).Logs.Single() as HandledErrorLog;
                semaphore.Release();
            }).ReturnsAsync("");

            Crashes.TrackError(mockException.Object);

            // Wait until the http layer sends the log.
            semaphore.Wait(2000);
            Assert.IsNotNull(actualLog);
            Assert.AreEqual(expectedStacktrace, actualLog.Exception.StackTrace);
        }
        public void TrackErrorWithValidParameters()
        {
            var             semaphore = new SemaphoreSlim(0);
            HandledErrorLog actualLog = null;

            Mock.Get(_mockNetworkAdapter).Setup(adapter => adapter.SendAsync(
                                                    It.IsAny <string>(),
                                                    It.IsAny <string>(),
                                                    It.IsAny <IDictionary <string, string> >(),
                                                    It.IsAny <string>(),
                                                    It.IsAny <CancellationToken>()))
            .Callback((string uri, string method, IDictionary <string, string> headers, string content, CancellationToken cancellation) =>
            {
                actualLog = JsonConvert.DeserializeObject <LogContainer>(content, LogSerializer.SerializationSettings).Logs.Single() as HandledErrorLog;
                semaphore.Release();
            }).ReturnsAsync("");
            var exception  = new System.Exception("Something went wrong.");
            var properties = new Dictionary <string, string> {
                { "k1", "v1" }, { "p2", "v2" }
            };

            Crashes.TrackError(exception, properties);

            // Wait until the http layer sends the log.
            semaphore.Wait(2000);
            Assert.IsNotNull(actualLog);
            Assert.AreEqual(exception.Message, actualLog.Exception.Message);
            CollectionAssert.AreEquivalent(properties, actualLog.Properties as Dictionary <string, string>);
        }
        public void TrackErrorWithUserId()
        {
            var semaphore = new SemaphoreSlim(0);
            var dummyUser = "******";

            UserIdContext.Instance.UserId = dummyUser;

            HandledErrorLog actualLog = null;

            Mock.Get(_mockNetworkAdapter).Setup(adapter => adapter.SendAsync(
                                                    It.IsAny <string>(),
                                                    It.IsAny <string>(),
                                                    It.IsAny <IDictionary <string, string> >(),
                                                    It.IsAny <string>(),
                                                    It.IsAny <CancellationToken>()))
            .Callback((string uri, string method, IDictionary <string, string> headers, string content, CancellationToken cancellation) =>
            {
                actualLog = JsonConvert.DeserializeObject <LogContainer>(content, LogSerializer.SerializationSettings).Logs.Single() as HandledErrorLog;
                semaphore.Release();
            }).ReturnsAsync("");
            var exception = new System.Exception("Something went wrong.");

            Crashes.TrackError(exception);

            // Wait until the http layer sends the log.
            semaphore.Wait(2000);
            Assert.IsNotNull(actualLog);
            Assert.AreEqual(dummyUser, actualLog.UserId);
        }
        public void TrackErrorWithTooManyProperties()
        {
            var             semaphore = new SemaphoreSlim(0);
            HandledErrorLog actualLog = null;

            Mock.Get(_mockNetworkAdapter).Setup(adapter => adapter.SendAsync(
                                                    It.IsAny <string>(),
                                                    It.IsAny <string>(),
                                                    It.IsAny <IDictionary <string, string> >(),
                                                    It.IsAny <string>(),
                                                    It.IsAny <CancellationToken>()))
            .Callback((string uri, string method, IDictionary <string, string> headers, string content, CancellationToken cancellation) =>
            {
                actualLog = JsonConvert.DeserializeObject <LogContainer>(content, LogSerializer.SerializationSettings).Logs.Single() as HandledErrorLog;
                semaphore.Release();
            }).ReturnsAsync("");
            var exception  = new System.Exception("Something went wrong.");
            var properties = new Dictionary <string, string>();

            for (int i = 0; i < PropertyValidator.MaxProperties + 5; ++i)
            {
                properties[i.ToString()] = i.ToString();
            }
            Crashes.TrackError(exception, properties);

            // Wait until the http layer sends the log.
            semaphore.Wait(2000);
            Assert.IsNotNull(actualLog);
            Assert.AreEqual(exception.Message, actualLog.Exception.Message);
            CollectionAssert.IsSubsetOf(actualLog.Properties as Dictionary <string, string>, properties);
            Assert.AreEqual(PropertyValidator.MaxProperties, actualLog.Properties.Count);
        }
Exemple #5
0
        public void LogError(Exception ex, MethodBase serviceMethodInfo, params object[] serviceParameterValues)
        {
            try
            {
                var innerMethodBase = (MethodBase)ex.Data[0];
                var innerParameters = (string)ex.Data[1];
                var stackTrace      = (StackTrace)ex.Data[2];
                int?lineNumber      = null;
                if (stackTrace != null)
                {
                    lineNumber = stackTrace.GetFrame(0)?.GetFileLineNumber();
                }

                var serviceParameterNames = serviceMethodInfo.GetParameters();
                var serviceParametersJs   = SerializeParameters(serviceParameterNames, serviceParameterValues, serviceMethodInfo);
                if (ex.GetType() == typeof(BusinessException))
                {
                    var itExc = (BusinessException)ex;
                    if (serviceMethodInfo.DeclaringType is { })
                    {
                        var errorLog = new HandledErrorLog()
                        {
                            CreateDateTime    = DateTime.Now,
                            ErrorCode         = itExc.Code,
                            ErrorMessage      = itExc.Message,
                            ServiceName       = serviceMethodInfo.DeclaringType.FullName,
                            ServiceMethodName = serviceMethodInfo.Name,
                            ServiceParameters = serviceParametersJs
                        };

                        _repoContext.HandledErrorLogs.Add(errorLog);
                    }

                    _repoContext.SaveChanges();
                }
        public void TrackErrorWhenDisabled()
        {
            var             logCount  = 0;
            var             semaphore = new SemaphoreSlim(0);
            HandledErrorLog actualLog = null;

            Mock.Get(_mockNetworkAdapter).Setup(adapter => adapter.SendAsync(
                                                    It.IsAny <string>(),
                                                    It.IsAny <string>(),
                                                    It.IsAny <IDictionary <string, string> >(),
                                                    It.IsAny <string>(),
                                                    It.IsAny <CancellationToken>()))
            .Callback((string uri, string method, IDictionary <string, string> headers, string content, CancellationToken cancellation) =>
            {
                actualLog = JsonConvert.DeserializeObject <LogContainer>(content, LogSerializer.SerializationSettings).Logs.Single() as HandledErrorLog;
                ++logCount;
                semaphore.Release();
            }).ReturnsAsync("");

            // If we disable the SDK.
            Crashes.SetEnabledAsync(false).Wait();

            // When we track an error.
            var exception  = new System.Exception("Something went wrong.");
            var properties = new Dictionary <string, string> {
                { "k1", "v1" }, { "p2", "v2" }
            };

            Crashes.TrackError(exception, properties);

            // Then it's not sent.
            semaphore.Wait(2000);
            Assert.IsNull(actualLog);

            // If we re-enable.
            Crashes.SetEnabledAsync(true).Wait();

            // When we track an error.
            Crashes.TrackError(exception, properties);

            // Then it's sent.
            semaphore.Wait(2000);
            Assert.IsNotNull(actualLog);
            Assert.AreEqual(1, logCount);
            Assert.AreEqual(exception.Message, actualLog.Exception.Message);
            Assert.IsNull(actualLog.Exception.StackTrace);
            CollectionAssert.AreEquivalent(properties, actualLog.Properties as Dictionary <string, string>);
        }
        public void TrackErrorWithPropertiesAndAttachments()
        {
            var                semaphore = new SemaphoreSlim(0);
            HandledErrorLog    actualLog = null;
            ErrorAttachmentLog actualErrorAttachmentLog = null;

            Mock.Get(_mockNetworkAdapter).Setup(adapter => adapter.SendAsync(
                                                    It.IsAny <string>(),
                                                    It.IsAny <string>(),
                                                    It.IsAny <IDictionary <string, string> >(),
                                                    It.IsAny <string>(),
                                                    It.IsAny <CancellationToken>()))
            .Callback((string uri, string method, IDictionary <string, string> headers, string content, CancellationToken cancellation) =>
            {
                var log = JsonConvert.DeserializeObject <LogContainer>(content, LogSerializer.SerializationSettings).Logs[0];
                if (log.GetType() == typeof(ErrorAttachmentLog))
                {
                    actualErrorAttachmentLog = log as ErrorAttachmentLog;
                }
                else
                {
                    actualLog = log as HandledErrorLog;
                }
                if (actualLog != null && actualErrorAttachmentLog != null)
                {
                    semaphore.Release();
                }
            }).ReturnsAsync("");

            var exception  = new System.Exception("Something went wrong.");
            var properties = new Dictionary <string, string> {
                { "k1", "v1" }, { "p2", "v2" }
            };
            var attachmentLog = GetValidErrorAttachmentLog();

            Crashes.TrackError(exception, properties, attachmentLog);

            // Wait until the http layer sends the log.
            semaphore.Wait(2000);
            Assert.IsNotNull(actualLog);
            Assert.AreEqual(exception.Message, actualLog.Exception.Message);
            Assert.IsNotNull(actualErrorAttachmentLog);
            Assert.AreEqual(actualLog.Id, actualErrorAttachmentLog.ErrorId);
            CollectionAssert.AreEquivalent(attachmentLog.Data, actualErrorAttachmentLog.Data);
            CollectionAssert.AreEquivalent(properties, actualLog.Properties as Dictionary <string, string>);
        }
        public void TrackErrorWithInvalidPropertiesAreSkipped()
        {
            var             semaphore = new SemaphoreSlim(0);
            HandledErrorLog actualLog = null;

            Mock.Get(_mockNetworkAdapter).Setup(adapter => adapter.SendAsync(
                                                    It.IsAny <string>(),
                                                    It.IsAny <string>(),
                                                    It.IsAny <IDictionary <string, string> >(),
                                                    It.IsAny <string>(),
                                                    It.IsAny <CancellationToken>()))
            .Callback((string uri, string method, IDictionary <string, string> headers, string content, CancellationToken cancellation) =>
            {
                actualLog = JsonConvert.DeserializeObject <LogContainer>(content, LogSerializer.SerializationSettings).Logs.Single() as HandledErrorLog;
                semaphore.Release();
            }).ReturnsAsync("");
            var exception  = new System.Exception("Something went wrong.");
            var properties = new Dictionary <string, string>
            {
                [""] = "testEmptyKeySkipped",
                ["testNullValueSkipped"] = null,
                [new string ('k', PropertyValidator.MaxPropertyKeyLength + 1)] = "testKeyTooLong",
                ["testValueTooLong"] = new string('v', PropertyValidator.MaxPropertyValueLength + 1),
                ["normalKey"]        = "normalValue"
            };

            Crashes.TrackError(exception, properties);

            // Wait until the http layer sends the log.
            semaphore.Wait(2000);
            Assert.IsNotNull(actualLog);
            Assert.AreEqual(exception.Message, actualLog.Exception.Message);

            // Check original dictionary not sent (copy is made).
            Assert.IsNotNull(actualLog.Properties);
            Assert.AreNotSame(properties, actualLog.Properties);

            // Check invalid values were skipped or truncated.
            Assert.AreEqual(3, actualLog.Properties.Count);
            Assert.AreEqual("normalValue", actualLog.Properties["normalKey"]);
            Assert.AreEqual("testKeyTooLong", actualLog.Properties[new string('k', PropertyValidator.MaxPropertyKeyLength)]);
            Assert.AreEqual(new string('v', PropertyValidator.MaxPropertyValueLength), actualLog.Properties["testValueTooLong"]);
        }