/// <summary>
        ///     Collects information from <c>Thread.CurrentThread</c> to a context called "Thread".
        /// </summary>
        /// <param name="context">Contains information about the currently processed exception and where it came from.</param>
        /// <returns>generated context info</returns>
        public ContextCollectionDTO Collect(IErrorReporterContext context)
        {
            var info = new ContextCollectionDTO(NAME);

            try
            {
                info.Properties.Add("Culture", Thread.CurrentThread.CurrentUICulture.IetfLanguageTag);
                info.Properties.Add("Id", Thread.CurrentThread.ManagedThreadId.ToString(CultureInfo.InvariantCulture));
                info.Properties.Add("Name", Thread.CurrentThread.Name);
                info.Properties.Add("IsBackground",
                                    Thread.CurrentThread.IsBackground.ToString(CultureInfo.InvariantCulture));
                if (Thread.CurrentThread.ExecutionContext != null)
                {
                    info.Properties.Add("ExecutionContext", Thread.CurrentThread.ExecutionContext.ToString());
                }
                info.Properties.Add("Priority", Thread.CurrentThread.Priority.ToString());
                info.Properties.Add("ThreadState", Thread.CurrentThread.ThreadState.ToString());
                info.Properties.Add("UICulture", Thread.CurrentThread.CurrentCulture.IetfLanguageTag);
            }
            catch (Exception ex)
            {
                info.Properties.Add("CollectionException", "Failed to fetch thread info: " + ex);
            }
            return(info);
        }
        /// <summary>
        ///     Collect information
        /// </summary>
        /// <param name="context">Context information provided by the class which reported the error.</param>
        /// <returns>
        ///     Collection. Items with multiple values are joined using <c>";;"</c>
        /// </returns>
        public ContextCollectionDTO Collect(IErrorReporterContext context)
        {
            var info = new ContextCollectionDTO(Name);

            info.Properties.Add("WorkingSet", Environment.WorkingSet.ToString(CultureInfo.InvariantCulture));
            info.Properties.Add("CurrentDirectory", Environment.CurrentDirectory);

            try
            {
                var process = Process.GetCurrentProcess();
                info.Properties.Add("ThreadCount", process.Threads.Count.ToString(CultureInfo.InvariantCulture));
                info.Properties.Add("StartTime", process.StartTime.ToString(CultureInfo.InvariantCulture));
                info.Properties.Add("TotalProcessorTime", process.TotalProcessorTime.ToString());
                info.Properties.Add("UserProcessorTime", process.UserProcessorTime.ToString());
                info.Properties.Add("HandleCount", process.HandleCount.ToString(CultureInfo.InvariantCulture));
                info.Properties.Add("ProcessName", process.ProcessName);
                info.Properties.Add("MainModule", process.MainModule.ToString());
                info.Properties.Add("BasePriority", process.BasePriority.ToString(CultureInfo.InvariantCulture));
                info.Properties.Add("VirtualMemorySize", process.VirtualMemorySize64.ToString(CultureInfo.InvariantCulture));
                info.Properties.Add("PrivateMemorySize", process.PrivateMemorySize64.ToString(CultureInfo.InvariantCulture));
            }
            catch (Exception ex)
            {
                info.Properties.Add("CollectionException", "Failed to fetch process info: " + ex);
            }

            return(info);
        }
        public override void Log(ExceptionLoggerContext context)
        {
            var data = "";

            if (context.Request.Content != null)
            {
                data = context.Request.Content.ReadAsStringAsync().Result;
            }

            _logger.Error("Request + " + context.Request.RequestUri + ", data" + data, context.Exception);
            _logger.Error(context.Exception);

            var properties = new Dictionary <string, string>
            {
                { "Url", context.Request.RequestUri.ToString() },
                { "HttpMethod", context.Request.Method.Method }
            };

            if (context.Request.Headers.Referrer != null)
            {
                properties.Add("Referer", context.Request.Headers.Referrer.ToString());
            }
            if (data.Length < 30000)
            {
                properties.Add("Body", data);
            }
            var collection = new ContextCollectionDTO("Request", properties);

            Err.Report(context.Exception, collection);
            base.Log(context);
        }
Example #4
0
        public ActionResult SimulatedFailure()
        {
            ViewBag.Title = "Hello";
            ViewBag.Model = new
            {
                state     = "Running",
                Collected = true
            };

            TempData["DemoKey"] = new
            {
                Amount  = 20000,
                Expires = DateTime.UtcNow.AddMinutes(5)
            };

            //throw new UnauthorizedAccessException();
            try
            {
                throw new InvalidOperationException("Tag demo");
            }
            catch (Exception ex)
            {
                var collection = new ContextCollectionDTO("User");
                collection.Properties.Add("Id", "53338");
                collection.Properties.Add("FirstName", "Jonas");
                collection.Properties.Add("LastName", "Gauffin");
                collection.Properties.Add("UserName", "jgauffin");
                var col2 = new ContextCollectionDTO("ViewModel");
                col2.Properties.Add("Fake", "Make");

                OneTrue.Report(ex, new [] { collection, col2 });
            }
            return(View());
        }
        private void Application_Error(object sender, EventArgs e)
        {
            var exception = Server.GetLastError();

            var data = "";

            if ((Request.InputStream != null) && (Request.InputStream.Length > 0))
            {
                var reader = new StreamReader(Request.InputStream);
                data = reader.ReadToEnd();
            }
            _logger.Error("Request + " + Request.Url + ", data" + data, exception);

            var properties = new Dictionary <string, string>
            {
                { "Url", Request.Url.ToString() },
                { "HttpMethod", Request.HttpMethod }
            };

            if (Request.UrlReferrer != null)
            {
                properties.Add("Referrer", Request.UrlReferrer.ToString());
            }
            if (data.Length < 30000)
            {
                properties.Add("Body", data);
            }
            properties.Add("ErrTags", "unhandled-exception");
            var collection = new ContextCollectionDTO("Request", properties);

            Err.Report(exception, collection);
        }
Example #6
0
        /// <summary>
        ///     Collect context information from all context providers.
        /// </summary>
        /// <param name="context">
        ///     CreateReport context (specialized for the different report adapters, for instance the ASP.NET
        ///     adapter contains the current <c>HttpContext</c>)
        /// </param>
        /// <remarks>
        /// <para>
        /// Collections are added to the <c>context.ContextCollections</c> property.
        /// </para>
        /// </remarks>
        /// <exception cref="System.ArgumentNullException">context</exception>
        public void Collect(IErrorReporterContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            foreach (var provider in _providers)
            {
                try
                {
                    var item = provider.Collect(context);
                    if (item == null)
                    {
                        continue;
                    }

                    context.ContextCollections.Add(item);
                }
                catch (Exception exception)
                {
                    var item = new ContextCollectionDTO(provider.Name,
                                                        new Dictionary <string, string> {
                        { "Error", exception.ToString() }
                    });
                    context.ContextCollections.Add(item);
                }
            }
        }
Example #7
0
        public static string GetProperty(this ContextCollectionDTO collection, string name)
        {
            if (collection.Properties.TryGetValue(name, out string value))
            {
                return(value);
            }

            var items = string.Join(", ", collection.Properties.Keys);

            throw new AssertionFailedException($"Property '{name}' was not found. Available properties are: {items}.");
        }
        public void Should_not_throw_exception_when_ThrowExceptions_is_true_and_report_upload_succeeds()
        {
            var uri           = new Uri($"http://localhost:{_listener.LocalPort}/coderr/");
            var collectionDto = new ContextCollectionDTO("MyName", new Dictionary <string, string> {
                { "Key", "Val" }
            });
            var report = new ErrorReportDTO("aaa", new ExceptionDTO(new Exception()), new[] { collectionDto });

            var sut = new UploadToCoderr(uri, "api", "secret", () => false, () => true);

            sut.UploadReport(report);
        }
Example #9
0
        /// <summary>
        ///     Get or create our collection
        /// </summary>
        /// <param name="context">context to find the collection in</param>
        /// <returns>collection</returns>
        public static ContextCollectionDTO GetCoderrCollection(this IErrorReporterContext2 context)
        {
            var collection = context.ContextCollections.FirstOrDefault(x => x.Name == "CoderrData");

            if (collection != null)
            {
                return(collection);
            }

            collection = new ContextCollectionDTO("CoderrData");
            context.ContextCollections.Add(collection);
            return(collection);
        }
 // ReSharper disable once UnusedMember.Local   //used through reflection
 private void ConvertDictionary <TKey, TValue>(string propertyName, IDictionary <TKey, TValue> value,
                                               ContextCollectionDTO contextCollection,
                                               List <object> path)
 {
     foreach (var kvp in value)
     {
         var key    = kvp.Key == null ? "null" : kvp.Key.ToString();
         var prefix = string.IsNullOrEmpty(propertyName)
             ? key
             : $"{propertyName}[{key}]";
         ReflectValue(prefix, kvp.Value, contextCollection, path);
     }
 }
Example #11
0
        /// <summary>
        ///     Get or create our collection
        /// </summary>
        /// <param name="collections">Collections array</param>
        /// <returns>collection</returns>
        public static ContextCollectionDTO GetCoderrCollection(this IList <ContextCollectionDTO> collections)
        {
            var collection = collections.FirstOrDefault(x => x.Name == "CoderrData");

            if (collection != null)
            {
                return(collection);
            }

            collection = new ContextCollectionDTO("CoderrData");
            collections.Add(collection);
            return(collection);
        }
        public static string Property <T>(this ContextCollectionDTO collection, string propertyName)
        {
            if (collection.Properties.TryGetValue(propertyName, out string value))
            {
                return(value);
            }

            var propertyNames = string.Join(",", collection.Properties.Keys);

            throw new AssertActualExpectedException(propertyName, null,
                                                    $"Failed to find property  \'{propertyName}\', existing properties: {propertyNames}."
                                                    );
        }
        public async Task <ReportDTO> GetAsync(int id)
        {
            ReportDTO report;

            using (var cmd = (DbCommand)_uow.CreateCommand())
            {
                cmd.CommandText =
                    "SELECT * FROM ErrorReports WHERE Id = @id";

                cmd.AddParameter("id", id);
                report = await cmd.FirstAsync <ReportDTO>();
            }

            var collections = new List <ContextCollectionDTO>();

            using (var cmd = (DbCommand)_uow.CreateCommand())
            {
                cmd.CommandText =
                    "SELECT Name, PropertyName, Value FROM ErrorReportCollectionProperties WHERE ReportId = @id ORDER BY Name";

                cmd.AddParameter("id", id);
                using (var reader = await cmd.ExecuteReaderAsync())
                {
                    string collectionName = null;
                    var    properties     = new Dictionary <string, string>();
                    while (await reader.ReadAsync())
                    {
                        var name = reader.GetString(0);
                        if (collectionName == null)
                        {
                            collectionName = name;
                        }

                        if (collectionName != name)
                        {
                            var collection = new ContextCollectionDTO(collectionName, properties);
                            collections.Add(collection);
                            properties     = new Dictionary <string, string>();
                            collectionName = name;
                        }

                        properties.Add(reader.GetString(1), reader.GetString(2));
                    }
                }
            }

            report.ContextCollections = collections.ToArray();
            return(report);
        }
Example #14
0
        public void Serialization_test()
        {
            var info = new ContextCollectionDTO("customer", new Dictionary <string, string>()
            {
                { "Key", "Value" }
            });
            DataContractSerializer serializer = new DataContractSerializer(typeof(ContextCollectionDTO));
            var ms = new MemoryStream();

            serializer.WriteObject(ms, info);
            ms.Position = 0;
            var obj = (ContextCollectionDTO)serializer.ReadObject(ms);

            obj.Name.Should().Be("customer");
        }
        internal void AddAddemblyVersion(IList <ContextCollectionDTO> contextInfo)
        {
            if (_configuration.ApplicationVersion == null)
            {
                return;
            }

            var items = new Dictionary <string, string>
            {
                { "AppAssemblyVersion", _configuration.ApplicationVersion }
            };

            var col = new ContextCollectionDTO("AppVersion", items);

            contextInfo.Add(col);
        }
Example #16
0
        public void Should_be_able_to_move_collection()
        {
            var ex  = new Exception();
            var col = new ContextCollectionDTO("MyName", new Dictionary <string, string>()
            {
                { "Key", "Value" }
            });

            ex.Data["ErrCollection.MyName"] = JsonConvert.SerializeObject(col);

            var sut = new ErrorReporterContext(this, ex);

            var actual = sut.GetCollectionProperty("MyName", "Key");

            actual.Should().Be("Value");
        }
        private ContextCollectionDTO ConvertDictionaryToCollection(string collectionName, IDictionary dictionary)
        {
            var path = new List <object>();

            if (collectionName == "Dictionary`2")
            {
                collectionName = "ContextData";
            }
            var collection = new ContextCollectionDTO(collectionName);

            foreach (DictionaryEntry kvp in dictionary)
            {
                var propertyName = kvp.Key?.ToString() ?? "null";
                ReflectValue(propertyName, kvp.Value, collection, path);
            }
            return(collection);
        }
Example #18
0
 /// <summary>
 ///     Collect information
 /// </summary>
 /// <param name="context">Context information provided by the class which reported the error.</param>
 /// <returns>
 ///     Collection. Items with multiple values are joined using <c>";;"</c>
 /// </returns>
 public ContextCollectionDTO Collect(IErrorReporterContext context)
 {
     try
     {
         var converter = new ObjectToContextCollectionConverter
         {
             MaxPropertyCount = Err.Configuration.MaxNumberOfPropertiesPerCollection
         };
         var collection = converter.Convert(context.Exception);
         collection.Name = "ExceptionProperties";
         return(collection);
     }
     catch (Exception ex)
     {
         var context2 = new ContextCollectionDTO("ExceptionProperties");
         context2.Properties.Add("ExceptionProperties.Error", ex.ToString());
         return(context2);
     }
 }
        /// <summary>
        ///     Use reflection on a complex object to add it's values to our context collection.
        /// </summary>
        /// <param name="propertyName">Property that this collection belongs to</param>
        /// <param name="value"></param>
        /// <param name="contextCollection">Collection that values should be added to.</param>
        /// <param name="path">To prevent circular references.</param>
        protected void ReflectValue(string propertyName, object value, ContextCollectionDTO contextCollection,
                                    List <object> path)
        {
            if (IsFilteredOut(value))
            {
                return;
            }

            if (value == null)
            {
                contextCollection.Properties.Add(propertyName, "null");
                return;
            }

            if (value is string)
            {
                contextCollection.Properties.Add(propertyName, value.ToString());
                return;
            }

            var enc = value as Encoding;

            if (enc != null)
            {
                contextCollection.Properties.Add(propertyName, enc.EncodingName);
                return;
            }
            var v1 = value as DateTimeFormatInfo;

            if (v1 != null)
            {
                contextCollection.Properties.Add(propertyName, v1.NativeCalendarName);
                return;
            }
            var v2 = value as CultureInfo;

            if (v2 != null)
            {
                contextCollection.Properties.Add(propertyName, "Culture[" + v2.LCID + "]");
                return;
            }
            if (IsSimpleType(value.GetType()) || propertyName == "Encoding")
            {
                contextCollection.Properties.Add(propertyName, value.ToString());
            }
            else
            {
                var dictIf   = GetGenericDictionaryInterface(value);
                var kvpTypes = GetKeyValuePairFromEnumeratorInterface(value);
                if (dictIf != null)
                {
                    _dictionaryConverterMethod.MakeGenericMethod(dictIf.GetGenericArguments())
                    .Invoke(this, new[] { propertyName, value, contextCollection, path });
                }
                else if (kvpTypes != null)
                {
                    _keyValuePairEnumeratorConverterMethod.MakeGenericMethod(kvpTypes)
                    .Invoke(this, new[] { propertyName, value, contextCollection, path });
                }

                else if (value is IDictionary)
                {
                    var items = value as IDictionary;
                    foreach (DictionaryEntry kvp in items)
                    {
                        var newPrefix = string.Format("{0}[{1}].", propertyName, kvp.Key);
                        ReflectObject(kvp.Value, newPrefix, contextCollection, path);
                    }
                }
                else if (value is IEnumerable)
                {
                    var items = value as IEnumerable;
                    var index = 0;
                    foreach (var item in items)
                    {
                        var newPrefix = string.Format("{0}[{1}].", propertyName, index);
                        ReflectObject(item, newPrefix, contextCollection, path);
                        index++;
                    }
                }
                else
                {
                    var newPrefix = propertyName + ".";

                    if (value.GetType() == typeof(Type))
                    {
                        contextCollection.Properties.Add(newPrefix, value.ToString());
                    }
                    else if (value.GetType() == typeof(Assembly))
                    {
                        contextCollection.Properties.Add(newPrefix, value.ToString());
                    }
                    else if (value.GetType().Namespace != null &&
                             value.GetType().Namespace.StartsWith("System.Reflection"))
                    {
                        contextCollection.Properties.Add(newPrefix, value.ToString());
                    }
                    else
                    {
                        ReflectObject(value, newPrefix, contextCollection, path);
                    }
                }
            }


            path.Remove(value);
        }
        /// <summary>
        ///     Use reflection on a complex object to add it's values to our context collection
        /// </summary>
        /// <param name="instance">Current object to reflect</param>
        /// <param name="prefix">Prefix, like "User.Address.Postal.ZipCode"</param>
        /// <param name="contextCollection">Collection that values should be added to.</param>
        /// <param name="path">To prevent circular references.</param>
        protected void ReflectObject(object instance, string prefix, ContextCollectionDTO contextCollection,
                                     List <object> path)
        {
            if (path.Contains(instance) || path.Count > 10 || MaxPropertyCount <= contextCollection.Properties.Count)
            {
                contextCollection.Properties.Add(prefix + "_error", "Circular reference or to deep hierarchy.");
                return;
            }
            if (IsFilteredOut(instance))
            {
                return;
            }

            path.Add(instance);

            foreach (var propInfo in instance.GetType().GetProperties())
            {
                //TODO: Add support.
                if (propInfo.GetIndexParameters().Length != 0)
                {
                    continue;
                }

                if (_propertiesToIgnore.Contains(propInfo.Name))
                {
                    continue;
                }

                var    propertyName = propInfo.Name;
                object value;
                try
                {
                    value = propInfo.GetValue(instance, null);
                }
                catch (Exception exception)
                {
                    contextCollection.Properties.Add(prefix + propertyName + "._error", exception.ToString());
                    continue;
                }

                if (_propertyFilter?.Invoke(propInfo.Name, value) == true)
                {
                    continue;
                }

                switch (value)
                {
                case null:
                    contextCollection.Properties.Add(prefix + propertyName, "null");
                    continue;

                case Encoding enc:
                    contextCollection.Properties.Add(prefix + propertyName, enc.EncodingName);
                    continue;

                case DateTimeFormatInfo v1:
                    contextCollection.Properties.Add(prefix + propertyName, v1.NativeCalendarName);
                    continue;

                case CultureInfo v2:
                    contextCollection.Properties.Add(prefix + propertyName, "Culture[" + v2.LCID + "]");
                    continue;
                }

                if (IsSimpleType(value.GetType()) || propertyName == "Encoding")
                {
                    contextCollection.Properties.Add(prefix + propertyName, value.ToString());
                }
                else
                {
                    var dictIf   = GetGenericDictionaryInterface(value);
                    var kvpTypes = GetKeyValuePairFromEnumeratorInterface(value);
                    if (dictIf != null)
                    {
                        _dictionaryConverterMethod.MakeGenericMethod(dictIf.GetGenericArguments())
                        .Invoke(this, new[] { propertyName, value, contextCollection, path });
                    }
                    else if (kvpTypes != null)
                    {
                        _keyValuePairEnumeratorConverterMethod.MakeGenericMethod(kvpTypes)
                        .Invoke(this, new[] { propertyName, value, contextCollection, path });
                    }
                    else if (value is IDictionary)
                    {
                        var items = value as IDictionary;
                        foreach (DictionaryEntry kvp in items)
                        {
                            var dictPropName = kvp.Key?.ToString() ?? "null";
                            var newPrefix    = $"{prefix}{propertyName}[{dictPropName}]";
                            ReflectValue(newPrefix, kvp.Value, contextCollection,
                                         path);
                        }
                    }
                    else if (value is IEnumerable)
                    {
                        var items = value as IEnumerable;
                        var index = 0;
                        foreach (var item in items)
                        {
                            var newPrefix = prefix == ""
                                ? $"{propertyName}[{index}]"
                                : $"{prefix}{propertyName}[{index}]";
                            ReflectValue(newPrefix, item, contextCollection, path);
                            index++;
                        }
                    }
                    else
                    {
                        var newPrefix = prefix == ""
                            ? propertyName + "."
                            : prefix + propertyName + ".";

                        if (propInfo.PropertyType == typeof(Type))
                        {
                            contextCollection.Properties.Add(newPrefix, value.ToString());
                        }
                        else if (propInfo.PropertyType == typeof(Assembly))
                        {
                            contextCollection.Properties.Add(newPrefix, value.ToString());
                        }
                        else if (propInfo.PropertyType.Namespace != null &&
                                 propInfo.PropertyType.Namespace.StartsWith("System.Reflection"))
                        {
                            contextCollection.Properties.Add(newPrefix, value.ToString());
                        }
                        else
                        {
                            ReflectObject(value, newPrefix, contextCollection, path);
                        }
                    }
                }
            }

            path.Remove(instance);
        }
        /// <summary>
        ///     Can be used to copy collections from an exception to a collection collection ;)
        /// </summary>
        /// <param name="exception">Exception that might contain collections</param>
        /// <param name="destination">target</param>
        public static void MoveCollectionsInException(Exception exception, IList <ContextCollectionDTO> destination)
        {
            var keysToRemove = new List <object>();

            foreach (var key in exception.Data.Keys)
            {
                var keyStr = key?.ToString();
                if (key == null)
                {
                    continue;
                }

                if (keyStr.Equals("ErrCollections") || keyStr.StartsWith("ErrCollections."))
                {
                    keysToRemove.Add(key);
                    var value = exception.Data[key];
                    if (!(value is string valueStr))
                    {
                        continue;
                    }

                    try
                    {
                        var data = JsonConvert.DeserializeObject <IEnumerable <ContextCollectionDTO> >(valueStr);
                        foreach (var col in data)
                        {
                            destination.Add(col);
                        }
                    }
                    catch (Exception ex)
                    {
                        var items = new Dictionary <string, string>()
                        {
                            { "MoveCollectionsInException.Err", ex.Message },
                            { "JSON", valueStr }
                        };
                        var col = new ContextCollectionDTO("ErrCollections", items);
                        destination.Add(col);
                    }
                }
                else if (keyStr.StartsWith("ErrCollection."))
                {
                    keysToRemove.Add(key);
                    var value = exception.Data[key];
                    if (!(value is string valueStr))
                    {
                        continue;
                    }

                    try
                    {
                        var col = JsonConvert.DeserializeObject <ContextCollectionDTO>(valueStr);
                        destination.Add(col);
                    }
                    catch (Exception ex)
                    {
                        var pos   = keyStr.IndexOf('.');
                        var items = new Dictionary <string, string>()
                        {
                            { "MoveCollectionsInException.Err", ex.Message },
                            { "JSON", valueStr }
                        };
                        var col = new ContextCollectionDTO(keyStr.Substring(pos + 1), items);
                        destination.Add(col);
                    }
                }
            }

            foreach (var key in keysToRemove)
            {
                exception.Data.Remove(key);
            }

            if (exception.InnerException != null)
            {
                MoveCollectionsInException(exception.InnerException, destination);
            }
        }
        /// <summary>
        ///     Use reflection on a complex object to add it's values to our context collection.
        /// </summary>
        /// <param name="propertyName">Property that this collection belongs to</param>
        /// <param name="value"></param>
        /// <param name="contextCollection">Collection that values should be added to.</param>
        /// <param name="path">To prevent circular references.</param>
        protected void ReflectValue(string propertyName, object value, ContextCollectionDTO contextCollection,
                                    List <object> path)
        {
            if (_propertyFilter?.Invoke(propertyName, value) == true)
            {
                return;
            }
            if (IsFilteredOut(value))
            {
                return;
            }

            switch (value)
            {
            case null:
                contextCollection.Properties.Add(propertyName, "null");
                return;

            case string _:
                contextCollection.Properties.Add(propertyName, value.ToString());
                return;

            case Encoding enc:
                contextCollection.Properties.Add(propertyName, enc.EncodingName);
                return;

            case DateTimeFormatInfo v1:
                contextCollection.Properties.Add(propertyName, v1.NativeCalendarName);
                return;

            case CultureInfo v2:
                contextCollection.Properties.Add(propertyName, "Culture[" + v2.LCID + "]");
                return;
            }

            if (IsSimpleType(value.GetType()) || propertyName == "Encoding")
            {
                contextCollection.Properties.Add(propertyName, value.ToString());
            }
            else
            {
                var dictIf   = GetGenericDictionaryInterface(value);
                var kvpTypes = GetKeyValuePairFromEnumeratorInterface(value);
                if (dictIf != null)
                {
                    _dictionaryConverterMethod.MakeGenericMethod(dictIf.GetGenericArguments())
                    .Invoke(this, new[] { propertyName, value, contextCollection, path });
                }
                else if (kvpTypes != null)
                {
                    _keyValuePairEnumeratorConverterMethod.MakeGenericMethod(kvpTypes)
                    .Invoke(this, new[] { propertyName, value, contextCollection, path });
                }

                else if (value is IDictionary)
                {
                    var items = value as IDictionary;
                    foreach (DictionaryEntry kvp in items)
                    {
                        var newPrefix = string.Format("{0}[{1}].", propertyName, kvp.Key);
                        ReflectObject(kvp.Value, newPrefix, contextCollection, path);
                    }
                }
                else if (value is IEnumerable items)
                {
                    var index = 0;
                    var sb    = new StringBuilder("[");
                    foreach (var item in items)
                    {
                        if (item != null && IsSimpleType(item.GetType()))
                        {
                            sb.Append(item);
                            sb.Append(',');
                        }
                        else
                        {
                            var newPrefix = $"{propertyName}[{index}].";
                            ReflectObject(item, newPrefix, contextCollection, path);
                        }
                        index++;
                    }
                    if (sb.Length > 1)
                    {
                        sb.Remove(sb.Length - 1, 1);
                        sb.Append(']');
                        contextCollection.Properties.Add(propertyName, sb.ToString());
                    }
                }
                else
                {
                    var newPrefix = propertyName + ".";

                    if (value.GetType() == typeof(Type))
                    {
                        contextCollection.Properties.Add(newPrefix, value.ToString());
                    }
                    else if (value.GetType() == typeof(Assembly))
                    {
                        contextCollection.Properties.Add(newPrefix, value.ToString());
                    }
                    else if (value.GetType().Namespace != null &&
                             value.GetType().Namespace.StartsWith("System.Reflection"))
                    {
                        contextCollection.Properties.Add(newPrefix, value.ToString());
                    }
                    else
                    {
                        ReflectObject(value, newPrefix, contextCollection, path);
                    }
                }
            }


            path.Remove(value);
        }
        // ReSharper disable once UnusedMember.Local   //used through reflection
        private void ConvertKvpEnumerator <TKey, TValue>(string propertyName,
                                                         IEnumerable <KeyValuePair <TKey, TValue> > enumerable, ContextCollectionDTO contextCollection,
                                                         List <object> path)
        {
            var index = 0;

            foreach (var kvp in enumerable)
            {
                var key    = kvp.Key == null ? "null" : kvp.Key.ToString();
                var prefix = string.IsNullOrEmpty(propertyName)
                    ? $"[{index++}]"
                    : $"{propertyName}[{index++}]";

                contextCollection.Properties.Add(prefix + ".Key", key);
                ReflectValue(prefix + ".Value", kvp.Value, contextCollection, path);
            }
        }
        /// <summary>
        ///     Turn an object into a string which can be used for debugging.
        /// </summary>
        /// <param name="collectionName">
        ///     Name of the collection that is being created. This name is displayed under "Similarities"
        ///     and "Context info" in our UI.
        /// </param>
        /// <param name="instance">Object to get a string representation for</param>
        /// <returns>"null" if the object is null, otherwise an string as given per object sample</returns>
        /// <remarks>
        ///     Look at the class doc for an example.
        /// </remarks>
        public ContextCollectionDTO Convert(string collectionName, object instance)
        {
            if (instance == null)
            {
                throw new ArgumentNullException("instance");
            }
            if (IsFilteredOut(instance))
            {
                return(new ContextCollectionDTO(collectionName,
                                                new Dictionary <string, string> {
                    { "Error", "The object type can not be traversed by codeRR" }
                }));
            }

            try
            {
                var dictIf = GetGenericDictionaryInterface(instance);
                if (dictIf != null)
                {
                    var contextCollection = new ContextCollectionDTO(collectionName);
                    var path = new List <object>();
                    _dictionaryConverterMethod.MakeGenericMethod(dictIf.GetGenericArguments())
                    .Invoke(this, new[] { "", instance, contextCollection, path });
                    return(contextCollection);
                }
                var kvpTypes = GetKeyValuePairFromEnumeratorInterface(instance);
                if (kvpTypes != null)
                {
                    var contextCollection = new ContextCollectionDTO(collectionName);
                    var path = new List <object>();
                    _keyValuePairEnumeratorConverterMethod.MakeGenericMethod(kvpTypes)
                    .Invoke(this, new[] { "", instance, contextCollection, path });
                    return(contextCollection);
                }
                if (instance is ContextCollectionDTO)
                {
                    return((ContextCollectionDTO)instance);
                }
                if (instance is IDictionary <string, string> )
                {
                    return(new ContextCollectionDTO(collectionName, (IDictionary <string, string>)instance));
                }
                if (instance is NameValueCollection)
                {
                    return(new ContextCollectionDTO(collectionName, (NameValueCollection)instance));
                }
                if (instance is IDictionary)
                {
                    return(ConvertDictionaryToCollection(collectionName, (IDictionary)instance));
                }
                var collection = new ContextCollectionDTO(collectionName);
                if (IsSimpleType(instance.GetType()))
                {
                    collection.Properties.Add("Value", instance.ToString());
                }
                else
                {
                    var path = new List <object>();
                    ReflectObject(instance, "", collection, path);
                }

                return(collection);
            }
            catch (Exception exception)
            {
                return(new ContextCollectionDTO("CoderrClientError",
                                                new Dictionary <string, string>
                {
                    { "Exception", exception.ToString() },
                    { "Type", instance.GetType().FullName },
                    { "Source", "ObjectToContextCollectionConverter" }
                }));
            }
        }
 /// <summary>
 ///     Creates a new instance of <see cref="PartitionContext" />.
 /// </summary>
 /// <param name="contextCollection">context to add partitions to.</param>
 /// <param name="reporterContext">
 ///     Context used when collecting all other context data (before partition collection is
 ///     invoked)
 /// </param>
 public PartitionContext(ContextCollectionDTO contextCollection, IErrorReporterContext reporterContext)
 {
     _contextCollection = contextCollection ?? throw new ArgumentNullException(nameof(contextCollection));
     ReporterContext    = reporterContext;
 }