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