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;
}