Пример #1
0
        public void Merge_CreatesNewFactories_WhenFactoryDefinitionsDifferent()
        {
            TracerFactory first = new TracerFactory();
            Match firstMatch = new Match() { AssemblyName = "Test", ClassName = "TestClass" };
            firstMatch.Matches.Add(new ExactMethodMatcher("TestMethod1", new[] { "ParamType1", "ParamType2" }));
            first.MatchDefinitions.Add(firstMatch);

            TracerFactory second = new TracerFactory("DifferentFactory", "TestFactory", "1", Metric.Scoped);
            Match secondMatch = new Match() { AssemblyName = firstMatch.AssemblyName, ClassName = firstMatch.ClassName };
            secondMatch.Matches.Add(new ExactMethodMatcher("TestMethod1", new[] { "ParamType1", "ParamType2" }));
            second.MatchDefinitions.Add(secondMatch);

            Extension firstExtension = new Extension();
            firstExtension.Instrumentation.TracerFactories.Add(first);

            Extension secondExtension = new Extension();
            secondExtension.Instrumentation.TracerFactories.Add(second);

            Extension merged = Extension.Merge(firstExtension, secondExtension);

            Assert.AreEqual(2, merged.Instrumentation.TracerFactories.Count);
            Assert.AreEqual(1, merged.Instrumentation.TracerFactories.Count(x => x.MetricName == "DifferentFactory" && x.Metric == Metric.Scoped));
            Assert.AreEqual(1, merged.Instrumentation.TracerFactories.Count(x => x.Name == "TestFactory" && x.Metric == Metric.Scoped));
            Assert.AreEqual(1, merged.Instrumentation.TracerFactories.Count(x => x.TransactionNamingPriority == "1" && x.Metric == Metric.Scoped));
            Assert.AreEqual(1, merged.Instrumentation.TracerFactories.Count(x => x.Metric == Metric.Unspecified));

            var different = merged.Instrumentation.TracerFactories.Where(x => x.MetricName == "DifferentFactory").First();
            var other = merged.Instrumentation.TracerFactories.Where(x => x != different).First();

            Assert.AreEqual(1, different.MatchDefinitions.Count);
            Assert.AreEqual(1, other.MatchDefinitions.Count);

            Assert.AreEqual("Test", different.MatchDefinitions.First().AssemblyName);
            Assert.AreEqual("Test", other.MatchDefinitions.First().AssemblyName);

            Assert.AreEqual("TestClass", different.MatchDefinitions.First().ClassName);
            Assert.AreEqual("TestClass", other.MatchDefinitions.First().ClassName);

            Assert.AreEqual(1, different.MatchDefinitions.First().Matches.Count());
            Assert.AreEqual(1, other.MatchDefinitions.First().Matches.Count());

            Assert.AreEqual(1, different.MatchDefinitions.First().Matches.Count(x => x.MethodName == "TestMethod1" && x.ParameterTypes == "ParamType1,ParamType2"));
            Assert.AreEqual(1, other.MatchDefinitions.First().Matches.Count(x => x.MethodName == "TestMethod1" && x.ParameterTypes == "ParamType1,ParamType2"));
        }
Пример #2
0
        public void Merge_CombinesExactMethodsMatchers_WhenContextSame()
        {
            TracerFactory first = new TracerFactory("MetricName", "Name", "1", Metric.Scoped);
            Match firstMatch = new Match() { AssemblyName = "Test", ClassName = "TestClass" };
            firstMatch.Matches.Add(new ExactMethodMatcher("TestMethod1", new[] { "ParamType1", "ParamType2" }));
            first.MatchDefinitions.Add(firstMatch);

            TracerFactory second = new TracerFactory("MetricName", "Name", "1", Metric.Scoped);
            Match secondMatch = new Match() { AssemblyName = firstMatch.AssemblyName, ClassName = firstMatch.ClassName };
            secondMatch.Matches.Add(new ExactMethodMatcher("TestMethod1", new[] { "ParamType3" }));
            second.MatchDefinitions.Add(secondMatch);

            Extension firstExtension = new Extension();
            firstExtension.Instrumentation.TracerFactories.Add(first);

            Extension secondExtension = new Extension();
            secondExtension.Instrumentation.TracerFactories.Add(second);

            Extension merged = Extension.Merge(firstExtension, secondExtension);

            Assert.AreEqual(1, merged.Instrumentation.TracerFactories.Count);

            var firstFactory = merged.Instrumentation.TracerFactories.First();
            Assert.AreEqual("MetricName", firstFactory.MetricName);
            Assert.AreEqual("Name", firstFactory.Name);
            Assert.AreEqual("1", firstFactory.TransactionNamingPriority);
            Assert.AreEqual(Metric.Scoped, firstFactory.Metric);
            Assert.IsNotNull(firstFactory.MatchDefinitions);

            var firstFactoryMatches = firstFactory.MatchDefinitions;
            Assert.AreEqual(1, firstFactoryMatches.Count());

            var firstFactoryMatch = firstFactoryMatches.First();
            Assert.AreEqual("Test", firstFactoryMatch.AssemblyName);
            Assert.AreEqual("TestClass", firstFactoryMatch.ClassName);

            var methodMatchers = firstFactoryMatch.Matches;
            Assert.AreEqual(2, methodMatchers.Count);

            Assert.AreEqual(2, methodMatchers.Count(x => x.MethodName == "TestMethod1"));
            Assert.AreEqual(1, methodMatchers.Count(x => x.MethodName == "TestMethod1" && x.ParameterTypes == "ParamType1,ParamType2"));
            Assert.AreEqual(1, methodMatchers.Count(x => x.MethodName == "TestMethod1" && x.ParameterTypes == "ParamType3"));
        }
Пример #3
0
        /// <summary>
        /// Produces a new Extension object that represents the union of all instrumentation
        /// targets specified in the supplied Extension objects.
        /// </summary>
        /// <param name="toMerge">The Extension objects to be merged.</param>
        /// <returns>A single Extension object that represents the combined instrumentation
        /// footprint described by all of the supplied Extension objects.</returns>
        public static Extension Merge(params Extension[] toMerge)
        {
            Extension toReturn = new Extension();

            var matchRecords = new Dictionary<DenormalisedExactMatchRecord, HashSet<ExactMethodMatcher>>();

            foreach (var factory in toMerge.SelectMany(x => x.Instrumentation.TracerFactories))
            {
                foreach (var match in factory.MatchDefinitions)
                {
                    DenormalisedExactMatchRecord matchRecord = new DenormalisedExactMatchRecord
                    {
                        Metric = factory.Metric,
                        MetricName = factory.MetricName,
                        Name = factory.Name,
                        TransactionNamingPriority = factory.TransactionNamingPriority,
                        AssemblyName = match.AssemblyName,
                        ClassName = match.ClassName
                    };

                    HashSet<ExactMethodMatcher> matchers = null;

                    if (!matchRecords.TryGetValue(matchRecord, out matchers))
                    {
                        matchers = matchRecords[matchRecord] = new HashSet<ExactMethodMatcher>();
                    }

                    matchers.UnionWith(match.Matches.Select(x => new ExactMethodMatcher { MethodName = x.MethodName, ParameterTypes = x.ParameterTypes }));
                }
            }

            // Group the records by factory details, then by assy/classname pair
            var keysByFactoryDetails = matchRecords.Keys.GroupBy(x => new { Metric = x.Metric, MetricName = x.MetricName, Name = x.Name, TransactionNamingPriority = x.TransactionNamingPriority});
            foreach (var factoryDetail in keysByFactoryDetails)
            {
                TracerFactory toAdd = new TracerFactory(factoryDetail.Key.MetricName, factoryDetail.Key.Name, factoryDetail.Key.TransactionNamingPriority, factoryDetail.Key.Metric);

                var byClassDetail = factoryDetail.GroupBy(x => new { AssemblyName = x.AssemblyName, ClassName = x.ClassName });
                foreach (var classDetail in byClassDetail)
                {
                    Match matchToAdd = new Match(classDetail.Key.AssemblyName, classDetail.Key.ClassName);

                    var matchRecord = new DenormalisedExactMatchRecord
                    {
                        Metric = toAdd.Metric,
                        MetricName = toAdd.MetricName,
                        Name = toAdd.Name,
                        TransactionNamingPriority = toAdd.TransactionNamingPriority,
                        AssemblyName = matchToAdd.AssemblyName,
                        ClassName = matchToAdd.ClassName
                    };

                    matchToAdd.Matches = matchRecords[matchRecord].OrderBy(x => x.MethodName).ThenBy(x => x.ParameterTypes).ToList();
                    toAdd.MatchDefinitions.Add(matchToAdd);
                }

                toAdd.MatchDefinitions = toAdd.MatchDefinitions.OrderBy(x => x.AssemblyName).ThenBy(x => x.ClassName).ToList();

                toReturn.Instrumentation.TracerFactories.Add(toAdd);
            }

            // Have tracer factories prefer unspecified metrics and metric names first, then others later
            toReturn.Instrumentation.TracerFactories =
                toReturn
                .Instrumentation
                .TracerFactories
                .OrderBy(x => x.Metric == Metric.Unspecified ? -1 : (int) x.Metric)
                .ThenBy(x => x.MetricName ?? string.Empty)
                .ThenBy(x => x.Name ?? string.Empty)
                .ThenBy(x => x.TransactionNamingPriority ?? string.Empty)
                .ToList();

            return toReturn;
        }
Пример #4
0
        public void Merge_DoesNotDuplicateMethodMatchers_WhenContextSame()
        {
            TracerFactory first = new TracerFactory();
            Match firstMatch = new Match() { AssemblyName = "Test", ClassName = "TestClass" };
            firstMatch.Matches.Add(new ExactMethodMatcher("TestMethod1", new[] { "ParamType1", "ParamType2" }));
            first.MatchDefinitions.Add(firstMatch);

            TracerFactory second = new TracerFactory();
            Match secondMatch = new Match() { AssemblyName = firstMatch.AssemblyName, ClassName = firstMatch.ClassName };
            secondMatch.Matches.Add(new ExactMethodMatcher("TestMethod1", new[] { "ParamType1", "ParamType2" }));
            second.MatchDefinitions.Add(secondMatch);

            Extension firstExtension = new Extension();
            firstExtension.Instrumentation.TracerFactories.Add(first);

            Extension secondExtension = new Extension();
            secondExtension.Instrumentation.TracerFactories.Add(second);

            Extension merged = Extension.Merge(firstExtension, secondExtension);

            Assert.AreEqual(1, merged.Instrumentation.TracerFactories.Count());
            Assert.IsTrue(string.IsNullOrWhiteSpace(merged.Instrumentation.TracerFactories.First().MetricName));
            Assert.AreEqual(Metric.Unspecified, merged.Instrumentation.TracerFactories.First().Metric);
            Assert.AreEqual(1, merged.Instrumentation.TracerFactories.First().MatchDefinitions.Count);

            var firstMergedMatch = merged.Instrumentation.TracerFactories.First().MatchDefinitions.First();
            Assert.AreEqual("Test", firstMergedMatch.AssemblyName);
            Assert.AreEqual("TestClass", firstMergedMatch.ClassName);
            Assert.AreEqual(1, firstMergedMatch.Matches.Count);

            Assert.AreEqual("TestMethod1", firstMergedMatch.Matches.First().MethodName);
            Assert.AreEqual("ParamType1,ParamType2", string.Join(",", firstMergedMatch.Matches.First().ParameterTypes));
        }
Пример #5
0
 /// <summary>
 /// Renders a supplied Extension object to a specified stream as a New Relic-compatible
 /// XML document.
 /// </summary>
 /// <param name="extension">The Extension object to be rendered.</param>
 /// <param name="stream">The stream to which the XML document should be rendered.</param>
 public static void RenderToStream(Extension extension, Stream stream)
 {
     XmlSerializer serializer = new XmlSerializer(typeof(Extension));
     serializer.Serialize(stream, extension);
 }
Пример #6
0
        /// <summary>
        /// Produces a new Extension object that represents the union of all instrumentation
        /// targets specified in the supplied Extension objects.
        /// </summary>
        /// <param name="toMerge">The Extension objects to be merged.</param>
        /// <returns>A single Extension object that represents the combined instrumentation
        /// footprint described by all of the supplied Extension objects.</returns>
        public static Extension Merge(params Extension[] toMerge)
        {
            Extension toReturn = new Extension();

            var matchRecords = new Dictionary <DenormalisedExactMatchRecord, HashSet <ExactMethodMatcher> >();

            foreach (var factory in toMerge.SelectMany(x => x.Instrumentation.TracerFactories))
            {
                foreach (var match in factory.MatchDefinitions)
                {
                    DenormalisedExactMatchRecord matchRecord = new DenormalisedExactMatchRecord
                    {
                        Metric     = factory.Metric,
                        MetricName = factory.MetricName,
                        Name       = factory.Name,
                        TransactionNamingPriority = factory.TransactionNamingPriority,
                        AssemblyName = match.AssemblyName,
                        ClassName    = match.ClassName
                    };

                    HashSet <ExactMethodMatcher> matchers = null;

                    if (!matchRecords.TryGetValue(matchRecord, out matchers))
                    {
                        matchers = matchRecords[matchRecord] = new HashSet <ExactMethodMatcher>();
                    }

                    matchers.UnionWith(match.Matches.Select(x => new ExactMethodMatcher {
                        MethodName = x.MethodName, ParameterTypes = x.ParameterTypes
                    }));
                }
            }

            // Group the records by factory details, then by assy/classname pair
            var keysByFactoryDetails = matchRecords.Keys.GroupBy(x => new { Metric = x.Metric, MetricName = x.MetricName, Name = x.Name, TransactionNamingPriority = x.TransactionNamingPriority });

            foreach (var factoryDetail in keysByFactoryDetails)
            {
                TracerFactory toAdd = new TracerFactory(factoryDetail.Key.MetricName, factoryDetail.Key.Name, factoryDetail.Key.TransactionNamingPriority, factoryDetail.Key.Metric);

                var byClassDetail = factoryDetail.GroupBy(x => new { AssemblyName = x.AssemblyName, ClassName = x.ClassName });
                foreach (var classDetail in byClassDetail)
                {
                    Match matchToAdd = new Match(classDetail.Key.AssemblyName, classDetail.Key.ClassName);

                    var matchRecord = new DenormalisedExactMatchRecord
                    {
                        Metric     = toAdd.Metric,
                        MetricName = toAdd.MetricName,
                        Name       = toAdd.Name,
                        TransactionNamingPriority = toAdd.TransactionNamingPriority,
                        AssemblyName = matchToAdd.AssemblyName,
                        ClassName    = matchToAdd.ClassName
                    };

                    matchToAdd.Matches = matchRecords[matchRecord].OrderBy(x => x.MethodName).ThenBy(x => x.ParameterTypes).ToList();
                    toAdd.MatchDefinitions.Add(matchToAdd);
                }

                toAdd.MatchDefinitions = toAdd.MatchDefinitions.OrderBy(x => x.AssemblyName).ThenBy(x => x.ClassName).ToList();

                toReturn.Instrumentation.TracerFactories.Add(toAdd);
            }

            // Have tracer factories prefer unspecified metrics and metric names first, then others later
            toReturn.Instrumentation.TracerFactories =
                toReturn
                .Instrumentation
                .TracerFactories
                .OrderBy(x => x.Metric == Metric.Unspecified ? -1 : (int)x.Metric)
                .ThenBy(x => x.MetricName ?? string.Empty)
                .ThenBy(x => x.Name ?? string.Empty)
                .ThenBy(x => x.TransactionNamingPriority ?? string.Empty)
                .ToList();

            return(toReturn);
        }