diff --git a/.gitignore b/.gitignore
index 9cd3777..5d38378 100644
--- a/.gitignore
+++ b/.gitignore
@@ -93,3 +93,6 @@ src/scaffolding.config
.idea/
*.sln.iml
src/ForIntegration/*
+src/Integration/Directory.Build.props
+
+.learningtransport
\ No newline at end of file
diff --git a/GitVersion.yml b/GitVersion.yml
index 613dd0e..16d2978 100644
--- a/GitVersion.yml
+++ b/GitVersion.yml
@@ -1,6 +1,8 @@
assembly-versioning-scheme: Major
-next-version: 1.0.0
+next-version: 2.0.0
commit-message-incrementing: Disabled
branches:
+ release:
+ tag: beta
develop:
- tag: alpha
+ tag: alpha
\ No newline at end of file
diff --git a/packaging/nuget/NServiceBus.Metrics.PerformanceCounters.nuspec b/packaging/nuget/NServiceBus.Metrics.PerformanceCounters.nuspec
deleted file mode 100644
index bfc7bfb..0000000
--- a/packaging/nuget/NServiceBus.Metrics.PerformanceCounters.nuspec
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
- NServiceBus.Metrics.PerformanceCounters
- NServiceBus Windows Performance Counters
- $version$
- $authors$
- $owners$
- $licenseUrl$
- $projectUrl$
- $iconUrl$
- $requireLicenseAcceptance$
- Enables access to performance counters
- $copyright$
- $tags$
-
-
-
-
-
-
-
-
-
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
new file mode 100644
index 0000000..965a519
--- /dev/null
+++ b/src/Directory.Build.props
@@ -0,0 +1,8 @@
+
+
+
+ latest
+ true
+
+
+
\ No newline at end of file
diff --git a/src/GuardTemplates.DotSettings b/src/GuardTemplates.DotSettings
deleted file mode 100644
index 4352395..0000000
--- a/src/GuardTemplates.DotSettings
+++ /dev/null
@@ -1,56 +0,0 @@
-
- True
- guard
- Guards against null arguments
- Guard.AgainstNull("$ARG$", $ARG$);
- True
- True
- Guard
- True
- True
- InCSharpStatement
- 2.0
- True
- complete()
- 0
- True
- guarde
- Guards against null or empty arguments
- Guard.AgainstNullAndEmpty("$ARG$", $ARG$);
- True
- True
- Guard
- True
- True
- InCSharpStatement
- 2.0
- True
- complete()
- 0
- True
- guardn
- Guard against negative arguments
- Guard.AgainstNegative("$ARG$", $ARG$);
- True
- True
- Guard
- True
- True
- InCSharpStatement
- 2.0
- True
- 0
- True
- guardnz
- Guards against negative and zero
- Guard.AgainstNegativeAndZero("$ARG$", $ARG$);
- True
- True
- Guard
- True
- True
- InCSharpStatement
- 2.0
- True
- complete()
- 0
\ No newline at end of file
diff --git a/src/Integration/Integration.sln b/src/Integration/Integration.sln
deleted file mode 100644
index 3a3e457..0000000
--- a/src/Integration/Integration.sln
+++ /dev/null
@@ -1,22 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 15
-VisualStudioVersion = 15.0.26403.3
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MyEndpoint", "MyEndpoint\MyEndpoint.csproj", "{C112D4A5-4A86-432F-8B5C-17B641ED6DC6}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {C112D4A5-4A86-432F-8B5C-17B641ED6DC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {C112D4A5-4A86-432F-8B5C-17B641ED6DC6}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {C112D4A5-4A86-432F-8B5C-17B641ED6DC6}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {C112D4A5-4A86-432F-8B5C-17B641ED6DC6}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
-EndGlobal
diff --git a/src/Integration/MyEndpoint/MyEndpoint.csproj b/src/Integration/MyEndpoint/MyEndpoint.csproj
deleted file mode 100644
index 53a2a07..0000000
--- a/src/Integration/MyEndpoint/MyEndpoint.csproj
+++ /dev/null
@@ -1,64 +0,0 @@
-
-
-
-
- Debug
- AnyCPU
- {C112D4A5-4A86-432F-8B5C-17B641ED6DC6}
- Exe
- MyEndpoint
- MyEndpoint
- v4.5.2
- 512
- true
-
-
- AnyCPU
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
-
-
- AnyCPU
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
-
-
-
- ..\..\packages\NServiceBus.6.2.1\lib\net452\NServiceBus.Core.dll
-
-
- ..\..\packages\NServiceBus.Metrics.1.0.0-alpha0065\lib\net452\NServiceBus.Metrics.dll
-
-
- False
- ..\..\ForIntegration\NServiceBus.Metrics.PerformanceCounters.dll
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Designer
-
-
-
-
-
\ No newline at end of file
diff --git a/src/Integration/MyEndpoint/Program.cs b/src/Integration/MyEndpoint/Program.cs
deleted file mode 100644
index 0340200..0000000
--- a/src/Integration/MyEndpoint/Program.cs
+++ /dev/null
@@ -1,47 +0,0 @@
-using System;
-using System.Threading.Tasks;
-using NServiceBus;
-
-namespace MyEndpoint
-{
- class Program
- {
- static void Main(string[] args)
- {
- AsyncMain().GetAwaiter().GetResult();
- }
-
- static async Task AsyncMain()
- {
- var configuration = new EndpointConfiguration("MyEndpoint");
- configuration.SendFailedMessagesTo("error");
- configuration.UsePersistence();
- configuration.UseTransport();
- configuration.EnableInstallers();
- var performanceCounters = configuration.EnableWindowsPerformanceCounters();
- performanceCounters.EnableSLAPerformanceCounters(TimeSpan.FromSeconds(1));
- var endpoint = await Endpoint.Start(configuration);
-
- ConsoleKeyInfo readKey;
- do
- {
- await endpoint.SendLocal(new MyMessage());
-
- readKey = Console.ReadKey();
- } while (readKey.Key != ConsoleKey.Escape);
-
- await endpoint.Stop();
- }
- }
-
- public class MyMessage : ICommand
- {
- }
-
- public class MyHandler : IHandleMessages {
- public Task Handle(MyMessage message, IMessageHandlerContext context)
- {
- return Task.Delay(2000);
- }
- }
-}
diff --git a/src/Integration/MyEndpoint/packages.config b/src/Integration/MyEndpoint/packages.config
deleted file mode 100644
index 3894d38..0000000
--- a/src/Integration/MyEndpoint/packages.config
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/src/NServiceBus.Metrics.PerformanceCounters.Tests/APIApprovals.Approve.approved.txt b/src/NServiceBus.Metrics.PerformanceCounters.Tests/APIApprovals.Approve.approved.txt
index d1f99ad..d40dc09 100644
--- a/src/NServiceBus.Metrics.PerformanceCounters.Tests/APIApprovals.Approve.approved.txt
+++ b/src/NServiceBus.Metrics.PerformanceCounters.Tests/APIApprovals.Approve.approved.txt
@@ -1,4 +1,6 @@
-namespace NServiceBus.Metrics.PerformanceCounters
+[assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute(@"NServiceBus.Metrics.PerformanceCounters.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100D32BC524DCB1205998C155A4F36BF873587D3602822ECD7B49CD775B2E6A006EE6B9164AB2E3103A6A4D1310C6E5C26818A32FE86710141A2D1F02EB564381CD64C88131BCCA478CDB5072F06DB991DE33DAC1C82BAF40D9F61DD6B40300A4673B693B51CD10A8B9B7D8AB64450431FA422514D6DABCAF70DF785B1E4E6E8AAF")]
+[assembly: System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.5.2", FrameworkDisplayName=".NET Framework 4.5.2")]
+namespace NServiceBus.Metrics.PerformanceCounters
{
[System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.All)]
public sealed class PerformanceCounterSettingsAttribute : System.Attribute
@@ -18,6 +20,8 @@ namespace NServiceBus
public class PerformanceCountersSettings
{
public void EnableSLAPerformanceCounters(System.TimeSpan sla) { }
+ [System.ObsoleteAttribute("This interval is no longer used for reporting. Counters values are updated as soo" +
+ "n as they are reported. Will be removed in version 3.0.0.", true)]
public void UpdateCounterEvery(System.TimeSpan updateInterval) { }
}
}
\ No newline at end of file
diff --git a/src/NServiceBus.Metrics.PerformanceCounters.Tests/APIApprovals.cs b/src/NServiceBus.Metrics.PerformanceCounters.Tests/APIApprovals.cs
index 9ce4329..8ad00a7 100644
--- a/src/NServiceBus.Metrics.PerformanceCounters.Tests/APIApprovals.cs
+++ b/src/NServiceBus.Metrics.PerformanceCounters.Tests/APIApprovals.cs
@@ -22,10 +22,12 @@ public void Approve()
string Filter(string text)
{
- return string.Join(Environment.NewLine, text.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries)
- .Where(l => !l.StartsWith("[assembly: "))
+ return string.Join(Environment.NewLine, text.Split(new[]
+ {
+ Environment.NewLine
+ }, StringSplitOptions.RemoveEmptyEntries)
+ .Where(l => !l.StartsWith("[assembly: ReleaseDateAttribute("))
.Where(l => !string.IsNullOrWhiteSpace(l))
- );
+ );
}
-
}
\ No newline at end of file
diff --git a/src/NServiceBus.Metrics.PerformanceCounters.Tests/App_Packages/PublicApiGenerator.6.0.0/ApiGenerator.cs b/src/NServiceBus.Metrics.PerformanceCounters.Tests/App_Packages/PublicApiGenerator.6.0.0/ApiGenerator.cs
deleted file mode 100644
index af61e83..0000000
--- a/src/NServiceBus.Metrics.PerformanceCounters.Tests/App_Packages/PublicApiGenerator.6.0.0/ApiGenerator.cs
+++ /dev/null
@@ -1,796 +0,0 @@
-using System;
-using System.CodeDom;
-using System.CodeDom.Compiler;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Reflection;
-using System.Text;
-using System.Text.RegularExpressions;
-using Microsoft.CSharp;
-using Mono.Cecil;
-using Mono.Cecil.Rocks;
-using ICustomAttributeProvider = Mono.Cecil.ICustomAttributeProvider;
-using TypeAttributes = System.Reflection.TypeAttributes;
-using System.Globalization;
-
-// ReSharper disable BitwiseOperatorOnEnumWithoutFlags
-namespace PublicApiGenerator
-{
- public static class ApiGenerator
- {
- public static string GeneratePublicApi(Assembly assemby, Type[] includeTypes = null, bool shouldIncludeAssemblyAttributes = true)
- {
- var assemblyResolver = new DefaultAssemblyResolver();
- var assemblyPath = assemby.Location;
- assemblyResolver.AddSearchDirectory(Path.GetDirectoryName(assemblyPath));
-
- var readSymbols = File.Exists(Path.ChangeExtension(assemblyPath, ".pdb"));
- var asm = AssemblyDefinition.ReadAssembly(assemblyPath, new ReaderParameters(ReadingMode.Deferred)
- {
- ReadSymbols = readSymbols,
- AssemblyResolver = assemblyResolver,
- });
-
- return CreatePublicApiForAssembly(asm, tr => includeTypes == null || includeTypes.Any(t => t.FullName == tr.FullName && t.Assembly.FullName == tr.Module.Assembly.FullName), shouldIncludeAssemblyAttributes);
- }
-
- // TODO: Assembly references?
- // TODO: Better handle namespaces - using statements? - requires non-qualified type names
- static string CreatePublicApiForAssembly(AssemblyDefinition assembly, Func shouldIncludeType, bool shouldIncludeAssemblyAttributes)
- {
- var publicApiBuilder = new StringBuilder();
- var cgo = new CodeGeneratorOptions
- {
- BracingStyle = "C",
- BlankLinesBetweenMembers = false,
- VerbatimOrder = false
- };
-
- using (var provider = new CSharpCodeProvider())
- {
- var compileUnit = new CodeCompileUnit();
- if (shouldIncludeAssemblyAttributes && assembly.HasCustomAttributes)
- {
- PopulateCustomAttributes(assembly, compileUnit.AssemblyCustomAttributes);
- }
-
- var publicTypes = assembly.Modules.SelectMany(m => m.GetTypes())
- .Where(t => !t.IsNested && ShouldIncludeType(t) && shouldIncludeType(t))
- .OrderBy(t => t.FullName);
- foreach (var publicType in publicTypes)
- {
- var @namespace = compileUnit.Namespaces.Cast()
- .FirstOrDefault(n => n.Name == publicType.Namespace);
- if (@namespace == null)
- {
- @namespace = new CodeNamespace(publicType.Namespace);
- compileUnit.Namespaces.Add(@namespace);
- }
-
- var typeDeclaration = CreateTypeDeclaration(publicType);
- @namespace.Types.Add(typeDeclaration);
- }
-
- using (var writer = new StringWriter())
- {
- provider.GenerateCodeFromCompileUnit(compileUnit, writer, cgo);
- var typeDeclarationText = NormaliseGeneratedCode(writer);
- publicApiBuilder.AppendLine(typeDeclarationText);
- }
- }
- return NormaliseLineEndings(publicApiBuilder.ToString().Trim());
- }
-
- static string NormaliseLineEndings(string value)
- {
- return Regex.Replace(value, @"\r\n|\n\r|\r|\n", Environment.NewLine);
- }
-
- static bool IsDelegate(TypeDefinition publicType)
- {
- return publicType.BaseType != null && publicType.BaseType.FullName == "System.MulticastDelegate";
- }
-
- static bool ShouldIncludeType(TypeDefinition t)
- {
- return (t.IsPublic || t.IsNestedPublic || t.IsNestedFamily) && !IsCompilerGenerated(t);
- }
-
- static bool ShouldIncludeMember(IMemberDefinition m)
- {
- return !IsCompilerGenerated(m) && !IsDotNetTypeMember(m) && !(m is FieldDefinition);
- }
-
- static bool IsCompilerGenerated(IMemberDefinition m)
- {
- return m.CustomAttributes.Any(a => a.AttributeType.FullName == "System.Runtime.CompilerServices.CompilerGeneratedAttribute");
- }
-
- static bool IsDotNetTypeMember(IMemberDefinition m)
- {
- if (m.DeclaringType == null || m.DeclaringType.FullName == null)
- return false;
- return m.DeclaringType.FullName.StartsWith("System") || m.DeclaringType.FullName.StartsWith("Microsoft");
- }
-
- static void AddMemberToTypeDeclaration(CodeTypeDeclaration typeDeclaration, IMemberDefinition memberInfo)
- {
- var methodDefinition = memberInfo as MethodDefinition;
- if (methodDefinition != null)
- {
- if (methodDefinition.IsConstructor)
- AddCtorToTypeDeclaration(typeDeclaration, methodDefinition);
- else
- AddMethodToTypeDeclaration(typeDeclaration, methodDefinition);
- }
- else if (memberInfo is PropertyDefinition)
- {
- AddPropertyToTypeDeclaration(typeDeclaration, (PropertyDefinition) memberInfo);
- }
- else if (memberInfo is EventDefinition)
- {
- typeDeclaration.Members.Add(GenerateEvent((EventDefinition)memberInfo));
- }
- else if (memberInfo is FieldDefinition)
- {
- AddFieldToTypeDeclaration(typeDeclaration, (FieldDefinition) memberInfo);
- }
- }
-
- static string NormaliseGeneratedCode(StringWriter writer)
- {
- var gennedClass = writer.ToString();
- const string autoGeneratedHeader = @"^//-+\s*$.*^//-+\s*$";
- const string emptyGetSet = @"\s+{\s+get\s+{\s+}\s+set\s+{\s+}\s+}";
- const string emptyGet = @"\s+{\s+get\s+{\s+}\s+}";
- const string emptySet = @"\s+{\s+set\s+{\s+}\s+}";
- const string getSet = @"\s+{\s+get;\s+set;\s+}";
- const string get = @"\s+{\s+get;\s+}";
- const string set = @"\s+{\s+set;\s+}";
- gennedClass = Regex.Replace(gennedClass, autoGeneratedHeader, string.Empty,
- RegexOptions.IgnorePatternWhitespace | RegexOptions.Multiline | RegexOptions.Singleline);
- gennedClass = Regex.Replace(gennedClass, emptyGetSet, " { get; set; }", RegexOptions.IgnorePatternWhitespace);
- gennedClass = Regex.Replace(gennedClass, getSet, " { get; set; }", RegexOptions.IgnorePatternWhitespace);
- gennedClass = Regex.Replace(gennedClass, emptyGet, " { get; }", RegexOptions.IgnorePatternWhitespace);
- gennedClass = Regex.Replace(gennedClass, emptySet, " { set; }", RegexOptions.IgnorePatternWhitespace);
- gennedClass = Regex.Replace(gennedClass, get, " { get; }", RegexOptions.IgnorePatternWhitespace);
- gennedClass = Regex.Replace(gennedClass, set, " { set; }", RegexOptions.IgnorePatternWhitespace);
- gennedClass = Regex.Replace(gennedClass, @"\s+{\s+}", " { }", RegexOptions.IgnorePatternWhitespace);
- gennedClass = Regex.Replace(gennedClass, @"\)\s+;", ");", RegexOptions.IgnorePatternWhitespace);
- return gennedClass;
- }
-
- static CodeTypeDeclaration CreateTypeDeclaration(TypeDefinition publicType)
- {
- if (IsDelegate(publicType))
- return CreateDelegateDeclaration(publicType);
-
- bool @static = false;
- TypeAttributes attributes = 0;
- if (publicType.IsPublic || publicType.IsNestedPublic)
- attributes |= TypeAttributes.Public;
- if (publicType.IsNestedFamily)
- attributes |= TypeAttributes.NestedFamily;
- if (publicType.IsSealed && !publicType.IsAbstract)
- attributes |= TypeAttributes.Sealed;
- else if (!publicType.IsSealed && publicType.IsAbstract && !publicType.IsInterface)
- attributes |= TypeAttributes.Abstract;
- else if (publicType.IsSealed && publicType.IsAbstract)
- @static = true;
-
- // Static support is a hack. CodeDOM does support it, and this isn't
- // correct C#, but it's good enough for our API outline
- var name = publicType.Name;
-
- var index = name.IndexOf('`');
- if (index != -1)
- name = name.Substring(0, index);
- var declaration = new CodeTypeDeclaration(@static ? "static " + name : name)
- {
- CustomAttributes = CreateCustomAttributes(publicType),
- // TypeAttributes must be specified before the IsXXX as they manipulate TypeAttributes!
- TypeAttributes = attributes,
- IsClass = publicType.IsClass,
- IsEnum = publicType.IsEnum,
- IsInterface = publicType.IsInterface,
- IsStruct = publicType.IsValueType && !publicType.IsPrimitive && !publicType.IsEnum,
- };
-
- if (declaration.IsInterface && publicType.BaseType != null)
- throw new NotImplementedException("Base types for interfaces needs testing");
-
- PopulateGenericParameters(publicType, declaration.TypeParameters);
-
- if (publicType.BaseType != null && ShouldOutputBaseType(publicType))
- {
- if (publicType.BaseType.FullName == "System.Enum")
- {
- var underlyingType = publicType.GetEnumUnderlyingType();
- if (underlyingType.FullName != "System.Int32")
- declaration.BaseTypes.Add(CreateCodeTypeReference(underlyingType));
- }
- else
- declaration.BaseTypes.Add(CreateCodeTypeReference(publicType.BaseType));
- }
- foreach(var @interface in publicType.Interfaces.OrderBy(i => i.FullName)
- .Select(t => new { Reference = t, Definition = t.Resolve() })
- .Where(t => ShouldIncludeType(t.Definition))
- .Select(t => t.Reference))
- declaration.BaseTypes.Add(CreateCodeTypeReference(@interface));
-
- foreach (var memberInfo in publicType.GetMembers().Where(ShouldIncludeMember).OrderBy(m => m.Name))
- AddMemberToTypeDeclaration(declaration, memberInfo);
-
- // Fields should be in defined order for an enum
- var fields = !publicType.IsEnum
- ? publicType.Fields.OrderBy(f => f.Name)
- : (IEnumerable)publicType.Fields;
- foreach (var field in fields)
- AddMemberToTypeDeclaration(declaration, field);
-
- foreach (var nestedType in publicType.NestedTypes.Where(ShouldIncludeType).OrderBy(t => t.FullName))
- {
- var nestedTypeDeclaration = CreateTypeDeclaration(nestedType);
- declaration.Members.Add(nestedTypeDeclaration);
- }
-
- return declaration;
- }
-
- static CodeTypeDeclaration CreateDelegateDeclaration(TypeDefinition publicType)
- {
- var invokeMethod = publicType.Methods.Single(m => m.Name == "Invoke");
- var name = publicType.Name;
- var index = name.IndexOf('`');
- if (index != -1)
- name = name.Substring(0, index);
- var declaration = new CodeTypeDelegate(name)
- {
- Attributes = MemberAttributes.Public,
- CustomAttributes = CreateCustomAttributes(publicType),
- ReturnType = CreateCodeTypeReference(invokeMethod.ReturnType),
- };
-
- // CodeDOM. No support. Return type attributes.
- PopulateCustomAttributes(invokeMethod.MethodReturnType, declaration.CustomAttributes, type => ModifyCodeTypeReference(type, "return:"));
- PopulateGenericParameters(publicType, declaration.TypeParameters);
- PopulateMethodParameters(invokeMethod, declaration.Parameters);
-
- // Of course, CodeDOM doesn't support generic type parameters for delegates. Of course.
- if (declaration.TypeParameters.Count > 0)
- {
- var parameterNames = from parameterType in declaration.TypeParameters.Cast()
- select parameterType.Name;
- declaration.Name = string.Format(CultureInfo.InvariantCulture, "{0}<{1}>", declaration.Name, string.Join(", ", parameterNames));
- }
-
- return declaration;
- }
-
- static bool ShouldOutputBaseType(TypeDefinition publicType)
- {
- return publicType.BaseType.FullName != "System.Object" && publicType.BaseType.FullName != "System.ValueType";
- }
-
- static void PopulateGenericParameters(IGenericParameterProvider publicType, CodeTypeParameterCollection parameters)
- {
- foreach (var parameter in publicType.GenericParameters)
- {
- if (parameter.HasCustomAttributes)
- throw new NotImplementedException("Attributes on type parameters is not supported. And weird");
-
- // A little hacky. Means we get "in" and "out" prefixed on any constraints, but it's either that
- // or add it as a custom attribute, which looks even weirder
- var name = parameter.Name;
- if (parameter.IsCovariant)
- name = "out " + name;
- if (parameter.IsContravariant)
- name = "in " + name;
-
- var typeParameter = new CodeTypeParameter(name)
- {
- HasConstructorConstraint =
- parameter.HasDefaultConstructorConstraint && !parameter.HasNotNullableValueTypeConstraint
- };
- if (parameter.HasNotNullableValueTypeConstraint)
- typeParameter.Constraints.Add(" struct"); // Extra space is a hack!
- if (parameter.HasReferenceTypeConstraint)
- typeParameter.Constraints.Add(" class");
- foreach (var constraint in parameter.Constraints.Where(t => t.FullName != "System.ValueType"))
- {
- typeParameter.Constraints.Add(CreateCodeTypeReference(constraint.GetElementType()));
- }
- parameters.Add(typeParameter);
- }
- }
-
- static CodeAttributeDeclarationCollection CreateCustomAttributes(ICustomAttributeProvider type)
- {
- var attributes = new CodeAttributeDeclarationCollection();
- PopulateCustomAttributes(type, attributes);
- return attributes;
- }
-
- static void PopulateCustomAttributes(ICustomAttributeProvider type,
- CodeAttributeDeclarationCollection attributes)
- {
- PopulateCustomAttributes(type, attributes, ctr => ctr);
- }
-
- static void PopulateCustomAttributes(ICustomAttributeProvider type,
- CodeAttributeDeclarationCollection attributes, Func codeTypeModifier)
- {
- foreach (var customAttribute in type.CustomAttributes.Where(ShouldIncludeAttribute).OrderBy(a => a.AttributeType.FullName).ThenBy(a => ConvertAttrbuteToCode(codeTypeModifier, a)))
- {
- var attribute = GenerateCodeAttributeDeclaration(codeTypeModifier, customAttribute);
- attributes.Add(attribute);
- }
- }
-
- static CodeAttributeDeclaration GenerateCodeAttributeDeclaration(Func codeTypeModifier, CustomAttribute customAttribute)
- {
- var attribute = new CodeAttributeDeclaration(codeTypeModifier(CreateCodeTypeReference(customAttribute.AttributeType)));
- foreach (var arg in customAttribute.ConstructorArguments)
- {
- attribute.Arguments.Add(new CodeAttributeArgument(CreateInitialiserExpression(arg)));
- }
- foreach (var field in customAttribute.Fields.OrderBy(f => f.Name))
- {
- attribute.Arguments.Add(new CodeAttributeArgument(field.Name, CreateInitialiserExpression(field.Argument)));
- }
- foreach (var property in customAttribute.Properties.OrderBy(p => p.Name))
- {
- attribute.Arguments.Add(new CodeAttributeArgument(property.Name, CreateInitialiserExpression(property.Argument)));
- }
- return attribute;
- }
-
- // Litee: This method is used for additional sorting of custom attributes when multiple values are allowed
- static object ConvertAttrbuteToCode(Func codeTypeModifier, CustomAttribute customAttribute)
- {
- using (var provider = new CSharpCodeProvider())
- {
- var cgo = new CodeGeneratorOptions
- {
- BracingStyle = "C",
- BlankLinesBetweenMembers = false,
- VerbatimOrder = false
- };
- var attribute = GenerateCodeAttributeDeclaration(codeTypeModifier, customAttribute);
- var declaration = new CodeTypeDeclaration("DummyClass")
- {
- CustomAttributes = new CodeAttributeDeclarationCollection(new[] { attribute }),
- };
- using (var writer = new StringWriter())
- {
- provider.GenerateCodeFromType(declaration, writer, cgo);
- return writer.ToString();
- }
- }
- }
-
- static readonly HashSet SkipAttributeNames = new HashSet
- {
- "System.CodeDom.Compiler.GeneratedCodeAttribute",
- "System.ComponentModel.EditorBrowsableAttribute",
- "System.Runtime.CompilerServices.AsyncStateMachineAttribute",
- "System.Runtime.CompilerServices.CompilerGeneratedAttribute",
- "System.Runtime.CompilerServices.CompilationRelaxationsAttribute",
- "System.Runtime.CompilerServices.ExtensionAttribute",
- "System.Runtime.CompilerServices.RuntimeCompatibilityAttribute",
- "System.Reflection.DefaultMemberAttribute",
- "System.Diagnostics.DebuggableAttribute",
- "System.Diagnostics.DebuggerNonUserCodeAttribute",
- "System.Diagnostics.DebuggerStepThroughAttribute",
- "System.Reflection.AssemblyCompanyAttribute",
- "System.Reflection.AssemblyConfigurationAttribute",
- "System.Reflection.AssemblyCopyrightAttribute",
- "System.Reflection.AssemblyDescriptionAttribute",
- "System.Reflection.AssemblyFileVersionAttribute",
- "System.Reflection.AssemblyInformationalVersionAttribute",
- "System.Reflection.AssemblyProductAttribute",
- "System.Reflection.AssemblyTitleAttribute",
- "System.Reflection.AssemblyTrademarkAttribute"
- };
-
- static bool ShouldIncludeAttribute(CustomAttribute attribute)
- {
- var attributeTypeDefinition = attribute.AttributeType.Resolve();
- return !SkipAttributeNames.Contains(attribute.AttributeType.FullName) && attributeTypeDefinition.IsPublic;
- }
-
- static CodeExpression CreateInitialiserExpression(CustomAttributeArgument attributeArgument)
- {
- if (attributeArgument.Value is CustomAttributeArgument)
- {
- return CreateInitialiserExpression((CustomAttributeArgument) attributeArgument.Value);
- }
-
- if (attributeArgument.Value is CustomAttributeArgument[])
- {
- var initialisers = from argument in (CustomAttributeArgument[]) attributeArgument.Value
- select CreateInitialiserExpression(argument);
- return new CodeArrayCreateExpression(CreateCodeTypeReference(attributeArgument.Type), initialisers.ToArray());
- }
-
- var type = attributeArgument.Type.Resolve();
- var value = attributeArgument.Value;
- if (type.BaseType != null && type.BaseType.FullName == "System.Enum")
- {
- var originalValue = Convert.ToInt64(value);
- if (type.CustomAttributes.Any(a => a.AttributeType.FullName == "System.FlagsAttribute"))
- {
- //var allFlags = from f in type.Fields
- // where f.Constant != null
- // let v = Convert.ToInt64(f.Constant)
- // where v == 0 || (originalValue & v) != 0
- // select (CodeExpression)new CodeFieldReferenceExpression(typeExpression, f.Name);
- //return allFlags.Aggregate((current, next) => new CodeBinaryOperatorExpression(current, CodeBinaryOperatorType.BitwiseOr, next));
-
- // I'd rather use the above, as it's just using the CodeDOM, but it puts
- // brackets around each CodeBinaryOperatorExpression
- var flags = from f in type.Fields
- where f.Constant != null
- let v = Convert.ToInt64(f.Constant)
- where v == 0 || (originalValue & v) != 0
- select type.FullName + "." + f.Name;
- return new CodeSnippetExpression(flags.Aggregate((current, next) => current + " | " + next));
- }
-
- var allFlags = from f in type.Fields
- where f.Constant != null
- let v = Convert.ToInt64(f.Constant)
- where v == originalValue
- select new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(CreateCodeTypeReference(type)), f.Name);
- return allFlags.FirstOrDefault();
- }
-
- if (type.FullName == "System.Type" && value is TypeReference)
- {
- return new CodeTypeOfExpression(CreateCodeTypeReference((TypeReference)value));
- }
-
- if (value is string)
- {
- // CodeDOM outputs a verbatim string. Any string with \n is treated as such, so normalise
- // it to make it easier for comparisons
- value = Regex.Replace((string)value, @"\n", "\\n");
- value = Regex.Replace((string)value, @"\r\n|\r\\n", "\\r\\n");
- }
-
- return new CodePrimitiveExpression(value);
- }
-
- static void AddCtorToTypeDeclaration(CodeTypeDeclaration typeDeclaration, MethodDefinition member)
- {
- if (member.IsAssembly || member.IsPrivate)
- return;
-
- var method = new CodeConstructor
- {
- CustomAttributes = CreateCustomAttributes(member),
- Name = member.Name,
- Attributes = GetMethodAttributes(member)
- };
- PopulateMethodParameters(member, method.Parameters);
-
- typeDeclaration.Members.Add(method);
- }
-
- static void AddMethodToTypeDeclaration(CodeTypeDeclaration typeDeclaration, MethodDefinition member)
- {
- if (member.IsAssembly || member.IsPrivate || member.IsSpecialName)
- return;
-
- var returnType = CreateCodeTypeReference(member.ReturnType);
-
- var method = new CodeMemberMethod
- {
- Name = member.Name,
- Attributes = GetMethodAttributes(member),
- CustomAttributes = CreateCustomAttributes(member),
- ReturnType = returnType,
- };
- PopulateCustomAttributes(member.MethodReturnType, method.ReturnTypeCustomAttributes);
- PopulateGenericParameters(member, method.TypeParameters);
- PopulateMethodParameters(member, method.Parameters, IsExtensionMethod(member));
-
- typeDeclaration.Members.Add(method);
- }
-
- static bool IsExtensionMethod(ICustomAttributeProvider method)
- {
- return method.CustomAttributes.Any(a => a.AttributeType.FullName == "System.Runtime.CompilerServices.ExtensionAttribute");
- }
-
- static void PopulateMethodParameters(IMethodSignature member,
- CodeParameterDeclarationExpressionCollection parameters, bool isExtension = false)
- {
- foreach (var parameter in member.Parameters)
- {
- FieldDirection direction = 0;
- if (parameter.IsOut)
- direction |= FieldDirection.Out;
- else if (parameter.ParameterType.IsByReference)
- direction |= FieldDirection.Ref;
-
- var parameterType = parameter.ParameterType.IsByReference
- ? parameter.ParameterType.GetElementType()
- : parameter.ParameterType;
-
- var type = CreateCodeTypeReference(parameterType);
-
- if (isExtension)
- {
- type = ModifyCodeTypeReference(type, "this");
- isExtension = false;
- }
-
- var name = parameter.HasConstant
- ? string.Format(CultureInfo.InvariantCulture, "{0} = {1}", parameter.Name, FormatParameterConstant(parameter))
- : parameter.Name;
- var expression = new CodeParameterDeclarationExpression(type, name)
- {
- Direction = direction,
- CustomAttributes = CreateCustomAttributes(parameter)
- };
- parameters.Add(expression);
- }
- }
-
- static object FormatParameterConstant(IConstantProvider parameter)
- {
- return parameter.Constant is string ? string.Format(CultureInfo.InvariantCulture, "\"{0}\"", parameter.Constant) : (parameter.Constant ?? "null");
- }
-
- static MemberAttributes GetMethodAttributes(MethodDefinition method)
- {
- MemberAttributes access = 0;
- if (method.IsFamily)
- access = MemberAttributes.Family;
- if (method.IsPublic)
- access = MemberAttributes.Public;
- if (method.IsAssembly)
- access = MemberAttributes.Assembly;
- if (method.IsFamilyAndAssembly)
- access = MemberAttributes.FamilyAndAssembly;
- if (method.IsFamilyOrAssembly)
- access = MemberAttributes.FamilyOrAssembly;
-
- MemberAttributes scope = 0;
- if (method.IsStatic)
- scope |= MemberAttributes.Static;
- if (method.IsFinal || !method.IsVirtual)
- scope |= MemberAttributes.Final;
- if (method.IsAbstract)
- scope |= MemberAttributes.Abstract;
- if (method.IsVirtual && !method.IsNewSlot)
- scope |= MemberAttributes.Override;
-
- MemberAttributes vtable = 0;
- if (IsHidingMethod(method))
- vtable = MemberAttributes.New;
-
- return access | scope | vtable;
- }
-
- static bool IsHidingMethod(MethodDefinition method)
- {
- var typeDefinition = method.DeclaringType;
-
- // If we're an interface, just try and find any method with the same signature
- // in any of the interfaces that we implement
- if (typeDefinition.IsInterface)
- {
- var interfaceMethods = from @interfaceReference in typeDefinition.Interfaces
- let interfaceDefinition = @interfaceReference.Resolve()
- where interfaceDefinition != null
- select interfaceDefinition.Methods;
-
- return interfaceMethods.Any(ms => MetadataResolver.GetMethod(ms, method) != null);
- }
-
- // If we're not an interface, find a base method that isn't virtual
- return !method.IsVirtual && GetBaseTypes(typeDefinition).Any(d => MetadataResolver.GetMethod(d.Methods, method) != null);
- }
-
- static IEnumerable GetBaseTypes(TypeDefinition type)
- {
- var baseType = type.BaseType;
- while (baseType != null)
- {
- var definition = baseType.Resolve();
- if (definition == null)
- yield break;
- yield return definition;
-
- baseType = baseType.DeclaringType;
- }
- }
-
- static void AddPropertyToTypeDeclaration(CodeTypeDeclaration typeDeclaration, PropertyDefinition member)
- {
- var getterAttributes = member.GetMethod != null ? GetMethodAttributes(member.GetMethod) : 0;
- var setterAttributes = member.SetMethod != null ? GetMethodAttributes(member.SetMethod) : 0;
-
- if (!HasVisiblePropertyMethod(getterAttributes) && !HasVisiblePropertyMethod(setterAttributes))
- return;
-
- var propertyAttributes = GetPropertyAttributes(getterAttributes, setterAttributes);
-
- var propertyType = member.PropertyType.IsGenericParameter
- ? new CodeTypeReference(member.PropertyType.Name)
- : CreateCodeTypeReference(member.PropertyType);
-
- var property = new CodeMemberProperty
- {
- Name = member.Name,
- Type = propertyType,
- Attributes = propertyAttributes,
- CustomAttributes = CreateCustomAttributes(member),
- HasGet = member.GetMethod != null && HasVisiblePropertyMethod(getterAttributes),
- HasSet = member.SetMethod != null && HasVisiblePropertyMethod(setterAttributes)
- };
-
- // Here's a nice hack, because hey, guess what, the CodeDOM doesn't support
- // attributes on getters or setters
- if (member.GetMethod != null && member.GetMethod.HasCustomAttributes)
- {
- PopulateCustomAttributes(member.GetMethod, property.CustomAttributes, type => ModifyCodeTypeReference(type, "get:"));
- }
- if (member.SetMethod != null && member.SetMethod.HasCustomAttributes)
- {
- PopulateCustomAttributes(member.SetMethod, property.CustomAttributes, type => ModifyCodeTypeReference(type, "set:"));
- }
-
- foreach (var parameter in member.Parameters)
- {
- property.Parameters.Add(
- new CodeParameterDeclarationExpression(CreateCodeTypeReference(parameter.ParameterType),
- parameter.Name));
- }
-
- // TODO: CodeDOM has no support for different access modifiers for getters and setters
- // TODO: CodeDOM has no support for attributes on setters or getters - promote to property?
-
- typeDeclaration.Members.Add(property);
- }
-
- static MemberAttributes GetPropertyAttributes(MemberAttributes getterAttributes, MemberAttributes setterAttributes)
- {
- MemberAttributes access = 0;
- var getterAccess = getterAttributes & MemberAttributes.AccessMask;
- var setterAccess = setterAttributes & MemberAttributes.AccessMask;
- if (getterAccess == MemberAttributes.Public || setterAccess == MemberAttributes.Public)
- access = MemberAttributes.Public;
- else if (getterAccess == MemberAttributes.Family || setterAccess == MemberAttributes.Family)
- access = MemberAttributes.Family;
- else if (getterAccess == MemberAttributes.FamilyAndAssembly || setterAccess == MemberAttributes.FamilyAndAssembly)
- access = MemberAttributes.FamilyAndAssembly;
- else if (getterAccess == MemberAttributes.FamilyOrAssembly || setterAccess == MemberAttributes.FamilyOrAssembly)
- access = MemberAttributes.FamilyOrAssembly;
- else if (getterAccess == MemberAttributes.Assembly || setterAccess == MemberAttributes.Assembly)
- access = MemberAttributes.Assembly;
- else if (getterAccess == MemberAttributes.Private || setterAccess == MemberAttributes.Private)
- access = MemberAttributes.Private;
-
- // Scope should be the same for getter and setter. If one isn't specified, it'll be 0
- var getterScope = getterAttributes & MemberAttributes.ScopeMask;
- var setterScope = setterAttributes & MemberAttributes.ScopeMask;
- var scope = (MemberAttributes) Math.Max((int) getterScope, (int) setterScope);
-
- // Vtable should be the same for getter and setter. If one isn't specified, it'll be 0
- var getterVtable = getterAttributes & MemberAttributes.VTableMask;
- var setterVtable = setterAttributes & MemberAttributes.VTableMask;
- var vtable = (MemberAttributes) Math.Max((int) getterVtable, (int) setterVtable);
-
- return access | scope | vtable;
- }
-
- static bool HasVisiblePropertyMethod(MemberAttributes attributes)
- {
- var access = attributes & MemberAttributes.AccessMask;
- return access == MemberAttributes.Public || access == MemberAttributes.Family ||
- access == MemberAttributes.FamilyOrAssembly;
- }
-
- static CodeTypeMember GenerateEvent(EventDefinition eventDefinition)
- {
- var @event = new CodeMemberEvent
- {
- Name = eventDefinition.Name,
- Attributes = MemberAttributes.Public | MemberAttributes.Final,
- CustomAttributes = CreateCustomAttributes(eventDefinition),
- Type = CreateCodeTypeReference(eventDefinition.EventType)
- };
-
- return @event;
- }
-
- static void AddFieldToTypeDeclaration(CodeTypeDeclaration typeDeclaration, FieldDefinition memberInfo)
- {
- if (memberInfo.IsPrivate || memberInfo.IsAssembly || memberInfo.IsSpecialName)
- return;
-
- MemberAttributes attributes = 0;
- if (memberInfo.HasConstant)
- attributes |= MemberAttributes.Const;
- if (memberInfo.IsFamily)
- attributes |= MemberAttributes.Family;
- if (memberInfo.IsPublic)
- attributes |= MemberAttributes.Public;
- if (memberInfo.IsStatic && !memberInfo.HasConstant)
- attributes |= MemberAttributes.Static;
-
- // TODO: Values for readonly fields are set in the ctor
- var codeTypeReference = CreateCodeTypeReference(memberInfo.FieldType);
- if (memberInfo.IsInitOnly)
- codeTypeReference = MakeReadonly(codeTypeReference);
- var field = new CodeMemberField(codeTypeReference, memberInfo.Name)
- {
- Attributes = attributes,
- CustomAttributes = CreateCustomAttributes(memberInfo)
- };
-
- if (memberInfo.HasConstant)
- field.InitExpression = new CodePrimitiveExpression(memberInfo.Constant);
-
- typeDeclaration.Members.Add(field);
- }
-
- static CodeTypeReference MakeReadonly(CodeTypeReference typeReference)
- {
- return ModifyCodeTypeReference(typeReference, "readonly");
- }
-
- static CodeTypeReference ModifyCodeTypeReference(CodeTypeReference typeReference, string modifier)
- {
- using (var provider = new CSharpCodeProvider())
- return new CodeTypeReference(modifier + " " + provider.GetTypeOutput(typeReference));
- }
-
- static CodeTypeReference CreateCodeTypeReference(TypeReference type)
- {
- var typeName = GetTypeName(type);
- return new CodeTypeReference(typeName, CreateGenericArguments(type));
- }
-
- static string GetTypeName(TypeReference type)
- {
- if (type.IsGenericParameter)
- return type.Name;
-
- if (!type.IsNested)
- {
- return (!string.IsNullOrEmpty(type.Namespace) ? (type.Namespace + ".") : "") + type.Name;
- }
-
- return GetTypeName(type.DeclaringType) + "." + type.Name;
- }
-
- static CodeTypeReference[] CreateGenericArguments(TypeReference type)
- {
- var genericInstance = type as IGenericInstance;
- if (genericInstance == null) return null;
-
- var genericArguments = new List();
- foreach (var argument in genericInstance.GenericArguments)
- {
- genericArguments.Add(CreateCodeTypeReference(argument));
- }
- return genericArguments.ToArray();
- }
- }
-
- static class CecilEx
- {
- public static IEnumerable GetMembers(this TypeDefinition type)
- {
- return type.Fields.Cast()
- .Concat(type.Methods)
- .Concat(type.Properties)
- .Concat(type.Events);
- }
- }
-}
diff --git a/src/NServiceBus.Metrics.PerformanceCounters.Tests/EndpointConfigBuilder.cs b/src/NServiceBus.Metrics.PerformanceCounters.Tests/EndpointConfigBuilder.cs
index 848a5d7..0062194 100644
--- a/src/NServiceBus.Metrics.PerformanceCounters.Tests/EndpointConfigBuilder.cs
+++ b/src/NServiceBus.Metrics.PerformanceCounters.Tests/EndpointConfigBuilder.cs
@@ -5,9 +5,10 @@ static class EndpointConfigBuilder
public static EndpointConfiguration BuildEndpoint(string s)
{
var endpointConfiguration = new EndpointConfiguration(s);
+ endpointConfiguration.UseTransport();
endpointConfiguration.SendFailedMessagesTo("error");
endpointConfiguration.EnableInstallers();
- endpointConfiguration.UseSerialization();
+ //endpointConfiguration.UseSerialization();
endpointConfiguration.UsePersistence();
var recoverability = endpointConfiguration.Recoverability();
recoverability.Immediate(c => c.NumberOfRetries(0));
diff --git a/src/NServiceBus.Metrics.PerformanceCounters.Tests/EstimatedTimeToSLABreachCounterTests.cs b/src/NServiceBus.Metrics.PerformanceCounters.Tests/EstimatedTimeToSLABreachCounterTests.cs
index 5715f9b..be3ff37 100644
--- a/src/NServiceBus.Metrics.PerformanceCounters.Tests/EstimatedTimeToSLABreachCounterTests.cs
+++ b/src/NServiceBus.Metrics.PerformanceCounters.Tests/EstimatedTimeToSLABreachCounterTests.cs
@@ -5,7 +5,7 @@
public class EstimatedTimeToSLABreachCounterTests
{
[Test]
- public void Single_Datapoint_should_result_in_MaxValue()
+ public void Single_DataPoint_should_result_in_MaxValue()
{
var mockPerformanceCounter = new MockIPerformanceCounter();
var counter = new EstimatedTimeToSLABreachCounter(TimeSpan.FromSeconds(2), mockPerformanceCounter);
diff --git a/src/NServiceBus.Metrics.PerformanceCounters.Tests/IntegrationTests.cs b/src/NServiceBus.Metrics.PerformanceCounters.Tests/IntegrationTests.cs
index a096475..a06d254 100644
--- a/src/NServiceBus.Metrics.PerformanceCounters.Tests/IntegrationTests.cs
+++ b/src/NServiceBus.Metrics.PerformanceCounters.Tests/IntegrationTests.cs
@@ -8,6 +8,7 @@
[TestFixture]
public class IntegrationTests
{
+ const string EndpointName = "PerfCountersIntegrationTests";
static ManualResetEvent ManualResetEvent = new ManualResetEvent(false);
[Test]
@@ -15,8 +16,7 @@ public async Task Ensure_counters_are_written()
{
string message = null;
- var endpointName = "PerfCountersIntegrationTests";
- var endpointConfiguration = EndpointConfigBuilder.BuildEndpoint(endpointName);
+ var endpointConfiguration = EndpointConfigBuilder.BuildEndpoint(EndpointName);
endpointConfiguration.DefineCriticalErrorAction(
context =>
{
@@ -27,11 +27,21 @@ public async Task Ensure_counters_are_written()
var performanceCounters = endpointConfiguration.EnableWindowsPerformanceCounters();
performanceCounters.EnableSLAPerformanceCounters(TimeSpan.FromSeconds(10));
- performanceCounters.UpdateCounterEvery(TimeSpan.FromSeconds(1));
var endpoint = await Endpoint.Start(endpointConfiguration)
.ConfigureAwait(false);
-
+
+ var criticalTime = GetCounter(PerformanceCountersFeature.CriticalTimeCounterName);
+ var processingTime = GetCounter(PerformanceCountersFeature.ProcessingTimeCounterName);
+
+ Assert.AreEqual(0, criticalTime.RawValue);
+ Assert.AreEqual(0, processingTime.RawValue);
+
+ var cancellation = new CancellationTokenSource();
+
+ var criticalTimeReading = ReadNonZero(criticalTime, cancellation);
+ var processingTimeReading = ReadNonZero(processingTime, cancellation);
+
await endpoint.SendLocal(new MyMessage())
.ConfigureAwait(false);
@@ -41,14 +51,13 @@ await Task.Delay(1500)
await endpoint.Stop()
.ConfigureAwait(false);
- var criticalTimePerfCounter = new PerformanceCounter("NServiceBus", PerformanceCountersFeature.CriticalTimeCounterName, endpointName, true);
- //var processingTimePerfCounter = new PerformanceCounter("NServiceBus", PerformanceCountersFeature.ProcessingTimeCounterName, endpointName, true);
- var slaPerCounter = new PerformanceCounter("NServiceBus", SLAMonitoringFeature.CounterName, endpointName, true);
- var messagesFailuresPerSecondCounter = new PerformanceCounter("NServiceBus", PerformanceCountersFeature.MessagesFailuresPerSecondCounterName, endpointName, true);
- var messagesProcessedPerSecondCounter = new PerformanceCounter("NServiceBus", PerformanceCountersFeature.MessagesProcessedPerSecondCounterName, endpointName, true);
- var messagesPulledPerSecondCounter = new PerformanceCounter("NServiceBus", PerformanceCountersFeature.MessagesPulledPerSecondCounterName, endpointName, true);
- Assert.AreNotEqual(0, criticalTimePerfCounter.RawValue);
- //Assert.AreNotEqual(0, processingTimePerfCounter.RawValue);
+ cancellation.Cancel();
+ var slaPerCounter = GetCounter(SLAMonitoringFeature.CounterName);
+ var messagesFailuresPerSecondCounter = GetCounter(PerformanceCountersFeature.MessagesFailuresPerSecondCounterName);
+ var messagesProcessedPerSecondCounter = GetCounter(PerformanceCountersFeature.MessagesProcessedPerSecondCounterName);
+ var messagesPulledPerSecondCounter = GetCounter(PerformanceCountersFeature.MessagesPulledPerSecondCounterName);
+ Assert.True(await criticalTimeReading);
+ Assert.True(await processingTimeReading);
Assert.AreNotEqual(0, slaPerCounter.RawValue);
Assert.AreEqual(0, messagesFailuresPerSecondCounter.RawValue);
Assert.AreNotEqual(0, messagesProcessedPerSecondCounter.RawValue);
@@ -57,12 +66,29 @@ await endpoint.Stop()
Assert.IsNull(message);
}
+ static async Task ReadNonZero(PerformanceCounter counter, CancellationTokenSource cancellation)
+ {
+ while (counter.RawValue == 0)
+ {
+ if (cancellation.IsCancellationRequested)
+ {
+ return false;
+ }
+
+ await Task.Delay(TimeSpan.FromMilliseconds(10));
+ }
+
+ return true;
+ }
+
+ static PerformanceCounter GetCounter(string counterName) => new PerformanceCounter("NServiceBus", counterName, EndpointName, true);
+
public class MyHandler : IHandleMessages
{
public Task Handle(MyMessage message, IMessageHandlerContext context)
{
ManualResetEvent.Set();
- return Task.Delay(TimeSpan.FromMilliseconds(100));
+ return Task.Delay(TimeSpan.FromMilliseconds(1000));
}
}
public class MyMessage : ICommand
diff --git a/src/NServiceBus.Metrics.PerformanceCounters.Tests/MockIPerformanceCounter.cs b/src/NServiceBus.Metrics.PerformanceCounters.Tests/MockIPerformanceCounter.cs
index 5885842..e7068e7 100644
--- a/src/NServiceBus.Metrics.PerformanceCounters.Tests/MockIPerformanceCounter.cs
+++ b/src/NServiceBus.Metrics.PerformanceCounters.Tests/MockIPerformanceCounter.cs
@@ -12,5 +12,10 @@ public void Increment()
RawValue++;
}
+ public void IncrementBy(long value)
+ {
+ RawValue += value;
+ }
+
public long RawValue { get; set; }
}
\ No newline at end of file
diff --git a/src/NServiceBus.Metrics.PerformanceCounters.Tests/NServiceBus.Metrics.PerformanceCounters.Tests.csproj b/src/NServiceBus.Metrics.PerformanceCounters.Tests/NServiceBus.Metrics.PerformanceCounters.Tests.csproj
index 7719bf9..c026f82 100644
--- a/src/NServiceBus.Metrics.PerformanceCounters.Tests/NServiceBus.Metrics.PerformanceCounters.Tests.csproj
+++ b/src/NServiceBus.Metrics.PerformanceCounters.Tests/NServiceBus.Metrics.PerformanceCounters.Tests.csproj
@@ -1,115 +1,30 @@
-
-
-
- Debug
- AnyCPU
- {9BCDA27A-5FC2-4197-9DCF-0D0F70424B58}
- Library
- Properties
- Tests
- Tests
- v4.5.2
- 512
-
-
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
- true
- false
-
-
- full
- false
- bin\Release\
- TRACE
- prompt
- 4
- true
- false
- true
-
+
+
+ net452
true
-
-
key.snk
+
-
- ..\packages\ApprovalTests.3.0.13\lib\net40\ApprovalTests.dll
- True
-
-
- ..\packages\ApprovalUtilities.3.0.13\lib\net45\ApprovalUtilities.dll
- True
-
-
- ..\packages\ApprovalUtilities.3.0.13\lib\net45\ApprovalUtilities.Net45.dll
- True
-
-
- ..\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.dll
- True
-
-
- ..\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.Mdb.dll
- True
-
-
- ..\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.Pdb.dll
- True
-
-
- ..\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.Rocks.dll
- True
-
-
- ..\packages\NServiceBus.6.3.4\lib\net452\NServiceBus.Core.dll
-
-
- ..\packages\NUnit.3.6.1\lib\net45\nunit.framework.dll
- True
-
-
-
-
-
-
+
+
-
- {df381b87-8eb9-4f30-9e92-0849641ed01a}
- NServiceBus.Metrics.PerformanceCounters
-
+
+
+
+
+
+
-
- CSharpCodeGenerationTests.Generates.approved.cs
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
+
-
+
\ No newline at end of file
diff --git a/src/NServiceBus.Metrics.PerformanceCounters.Tests/PerformanceCounterUpdaterTests.cs b/src/NServiceBus.Metrics.PerformanceCounters.Tests/PerformanceCounterUpdaterTests.cs
index ccc79cc..e0495e4 100644
--- a/src/NServiceBus.Metrics.PerformanceCounters.Tests/PerformanceCounterUpdaterTests.cs
+++ b/src/NServiceBus.Metrics.PerformanceCounters.Tests/PerformanceCounterUpdaterTests.cs
@@ -2,7 +2,12 @@
{
using System;
using System.Collections.Generic;
+ using System.Diagnostics;
+ using System.Linq;
using System.Threading;
+ using System.Threading.Tasks;
+ using ApprovalUtilities.Utilities;
+ using NServiceBus;
using NUnit.Framework;
[TestFixture]
@@ -11,58 +16,36 @@ public class PerformanceCounterUpdaterTests
[Test]
public void Meters_within_payload_should_be_converted_into_performance_counters()
{
+ var endpointName = "Sender@af016c07";
var cache = new MockPerformanceCountersCache();
- var sut = new PerformanceCounterUpdater(cache, new Dictionary());
- sut.Update(PayloadWithRandomMeters);
+ var signals = new[]
+ {
+ new MockSignalProbe("signal 1"),
+ new MockSignalProbe("signal 2"),
+ new MockSignalProbe("signal 3"),
+ };
+
+ var sut = new PerformanceCounterUpdater(cache, new Dictionary(), endpointName);
+
+ sut.Observe(new ProbeContext(new IDurationProbe[0], signals));
+
+ var e = new SignalEvent();
+ Enumerable.Range(0, 111).ForEach(_ => signals[0].Observers(ref e));
+ Enumerable.Range(0, 222).ForEach(_ => signals[1].Observers(ref e));
+ Enumerable.Range(0, 333).ForEach(_ => signals[2].Observers(ref e));
- var performanceCounterOne = cache.Get(new CounterInstanceName("meter 1", "Sender@af016c07"));
- var performanceCounterTwo = cache.Get(new CounterInstanceName("meter 2", "Sender@af016c07"));
- var performanceCounterThree = cache.Get(new CounterInstanceName("meter 3", "Sender@af016c07"));
+ var performanceCounterOne = cache.Get(new CounterInstanceName(signals[0].Name, endpointName));
+ var performanceCounterTwo = cache.Get(new CounterInstanceName(signals[1].Name, endpointName));
+ var performanceCounterThree = cache.Get(new CounterInstanceName(signals[2].Name, endpointName));
Assert.AreEqual(111, performanceCounterOne.RawValue);
Assert.AreEqual(222, performanceCounterTwo.RawValue);
Assert.AreEqual(333, performanceCounterThree.RawValue);
}
- const string PayloadWithRandomMeters = @"{
- ""Context"": ""Sender@af016c07"",
- ""Meters"": [
- {
- ""Name"": ""meter 1"",
- ""Count"": 111,
- ""MeanRate"": 0.0,
- ""OneMinuteRate"": 0.0,
- ""FiveMinuteRate"": 0.0,
- ""FifteenMinuteRate"": 0.0,
- ""Unit"": ""Messages"",
- ""RateUnit"": ""s""
- },
- {
- ""Name"": ""meter 2"",
- ""Count"": 222,
- ""MeanRate"": 0.0,
- ""OneMinuteRate"": 0.0,
- ""FiveMinuteRate"": 0.0,
- ""FifteenMinuteRate"": 0.0,
- ""Unit"": ""Messages"",
- ""RateUnit"": ""s""
- },
- {
- ""Name"": ""meter 3"",
- ""Count"": 333,
- ""MeanRate"": 0.0,
- ""OneMinuteRate"": 0.0,
- ""FiveMinuteRate"": 0.0,
- ""FifteenMinuteRate"": 0.0,
- ""Unit"": ""Messages"",
- ""RateUnit"": ""s""
- }
- ]
- }";
-
[Test]
- public void Meters_that_need_mapping_within_payload_should_be_converted_into_performance_counters()
+ public void Signals_that_map_to_legacy_names_should_be_converted_to_counters_with_queueAddress_as_instance_name()
{
var cache = new MockPerformanceCountersCache();
@@ -73,9 +56,22 @@ public void Meters_that_need_mapping_within_payload_should_be_converted_into_per
{ "# of messages successfully processed / sec", new CounterInstanceName("# of msgs successfully processed / sec", "queueAddress") },
};
- var sut = new PerformanceCounterUpdater(cache, legacyInstanceNameMap);
+ var sut = new PerformanceCounterUpdater(cache, legacyInstanceNameMap, "Sender@af016c07");
+
+ var signals = new[]
+ {
+ new MockSignalProbe("# of message failures / sec"),
+ new MockSignalProbe("# of messages pulled from the input queue / sec"),
+ new MockSignalProbe("# of messages successfully processed / sec"),
+ };
+
+ sut.Observe(new ProbeContext(new IDurationProbe[0], signals));
+
+ var e = new SignalEvent();
- sut.Update(PayloadWithNewMeterNamesThatNeedToBeMappedToLegacyMeterNames);
+ Enumerable.Range(0, 111).ForEach(_ => signals[0].Observers(ref e));
+ Enumerable.Range(0, 222).ForEach(_ => signals[1].Observers(ref e));
+ Enumerable.Range(0, 333).ForEach(_ => signals[2].Observers(ref e));
var performanceCounterOne = cache.Get(new CounterInstanceName("# of msgs failures / sec", "queueAddress"));
var performanceCounterTwo = cache.Get(new CounterInstanceName("# of msgs pulled from the input queue /sec", "queueAddress"));
@@ -86,153 +82,145 @@ public void Meters_that_need_mapping_within_payload_should_be_converted_into_per
Assert.AreEqual(333, performanceCounterThree.RawValue);
}
- const string PayloadWithNewMeterNamesThatNeedToBeMappedToLegacyMeterNames = @"{
- ""Context"": ""Sender@af016c07"",
- ""Meters"": [
- {
- ""Name"": ""# of message failures / sec"",
- ""Count"": 111,
- ""MeanRate"": 0.0,
- ""OneMinuteRate"": 0.0,
- ""FiveMinuteRate"": 0.0,
- ""FifteenMinuteRate"": 0.0,
- ""Unit"": ""Messages"",
- ""RateUnit"": ""s""
- },
- {
- ""Name"": ""# of messages pulled from the input queue / sec"",
- ""Count"": 222,
- ""MeanRate"": 0.0,
- ""OneMinuteRate"": 0.0,
- ""FiveMinuteRate"": 0.0,
- ""FifteenMinuteRate"": 0.0,
- ""Unit"": ""Messages"",
- ""RateUnit"": ""s""
- },
- {
- ""Name"": ""# of messages successfully processed / sec"",
- ""Count"": 333,
- ""MeanRate"": 0.0,
- ""OneMinuteRate"": 0.0,
- ""FiveMinuteRate"": 0.0,
- ""FifteenMinuteRate"": 0.0,
- ""Unit"": ""Messages"",
- ""RateUnit"": ""s""
- }
- ]
- }";
[Test]
- public void Timers_within_payload_should_be_converted_into_performance_counters()
+ public void Duration_probes_within_payload_should_be_converted_into_performance_counters()
{
var cache = new MockPerformanceCountersCache();
- var sut = new PerformanceCounterUpdater(cache, new Dictionary());
+ var sut = new PerformanceCounterUpdater(cache, new Dictionary(), "Sender@af016c07");
- sut.Update(PayloadWithRandomTimers);
+ var durationProbes = new[]
+ {
+ new MockDurationProbe("Critical Time"),
+ new MockDurationProbe("Processing Time")
+ };
- var performanceCounterOne = cache.Get(new CounterInstanceName("Critical Time", "Sender@af016c07"));
- var performanceCounterTwo = cache.Get(new CounterInstanceName("Processing Time", "Sender@af016c07"));
+ sut.Observe(new ProbeContext(durationProbes, new ISignalProbe[0]));
- Assert.AreEqual(11, performanceCounterOne.RawValue);
- Assert.AreEqual(22, performanceCounterTwo.RawValue);
+ var timeSpan1 = TimeSpan.FromSeconds(11);
+ var d1 = new DurationEvent(timeSpan1, null);
+ durationProbes[0].Observers(ref d1);
+
+ var timeSpan2 = TimeSpan.FromSeconds(22);
+ var d2 = new DurationEvent(timeSpan2, null);
+ durationProbes[1].Observers(ref d2);
+
+ // asserting the number of accessed counters
+ Assert.AreEqual(3 + 3, cache.Count);
+
+ var counter1 = cache.Get(new CounterInstanceName("Critical Time", "Sender@af016c07"));
+ var counter1average = cache.Get(new CounterInstanceName("Critical Time Average", "Sender@af016c07"));
+ var counter1averageBase = cache.Get(new CounterInstanceName("Critical Time AverageBase", "Sender@af016c07"));
+
+ var counter2 = cache.Get(new CounterInstanceName("Processing Time", "Sender@af016c07"));
+ var counter2average = cache.Get(new CounterInstanceName("Processing Time Average", "Sender@af016c07"));
+ var counter2averageBase = cache.Get(new CounterInstanceName("Processing Time AverageBase", "Sender@af016c07"));
+
+ Assert.AreEqual(11, counter1.RawValue);
+ Assert.AreEqual(CalculateAverageTimerCounterUpdate(timeSpan1), counter1average.RawValue);
+ Assert.AreEqual(1, counter1averageBase.RawValue);
+
+ Assert.AreEqual(22, counter2.RawValue);
+ Assert.AreEqual(CalculateAverageTimerCounterUpdate(timeSpan2), counter2average.RawValue);
+ Assert.AreEqual(1, counter2averageBase.RawValue);
}
- const string PayloadWithRandomTimers = @"{
- ""Context"": ""Sender@af016c07"",
- ""Timers"": [
- {
- ""Name"": ""Critical Time"",
- ""Count"": 0,
- ""ActiveSessions"": 0,
- ""TotalTime"": 11,
- ""Rate"": {
- ""MeanRate"": 0.0,
- ""OneMinuteRate"": 0.0,
- ""FiveMinuteRate"": 0.0,
- ""FifteenMinuteRate"": 0.0
- },
- ""Histogram"": {
- ""LastValue"": 11000.0,
- ""Min"": 0.0,
- ""Mean"": 0.0,
- ""StdDev"": 0.0,
- ""Median"": 0.0,
- ""Percentile75"": 0.0,
- ""Percentile95"": 0.0,
- ""Percentile98"": 0.0,
- ""Percentile99"": 0.0,
- ""Percentile999"": 0.0,
- ""SampleSize"": 0
- },
- ""Unit"": ""Messages"",
- ""RateUnit"": ""s"",
- ""DurationUnit"": ""ms""
- },
- {
- ""Name"": ""Processing Time"",
- ""Count"": 0,
- ""ActiveSessions"": 0,
- ""TotalTime"": 22,
- ""Rate"": {
- ""MeanRate"": 0.0,
- ""OneMinuteRate"": 0.0,
- ""FiveMinuteRate"": 0.0,
- ""FifteenMinuteRate"": 0.0
- },
- ""Histogram"": {
- ""LastValue"": 22000.0,
- ""Min"": 0.0,
- ""Mean"": 0.0,
- ""StdDev"": 0.0,
- ""Median"": 0.0,
- ""Percentile75"": 0.0,
- ""Percentile95"": 0.0,
- ""Percentile98"": 0.0,
- ""Percentile99"": 0.0,
- ""Percentile999"": 0.0,
- ""SampleSize"": 0
- },
- ""Unit"": ""Messages"",
- ""RateUnit"": ""s"",
- ""DurationUnit"": ""ms""
- }
- ]
- }";
[Test]
- public void Timers_within_payload_should_be_reported_as_zeros_after_specific_period_from_last_observed_pipeline_completion()
+ public void Duration_probes_within_payload_should_be_converted_into_performance_counters_with_no_raw_value_if_not_critical_or_processing_time()
+ {
+ var cache = new MockPerformanceCountersCache();
+ var sut = new PerformanceCounterUpdater(cache, new Dictionary(), "Sender@af016c07");
+
+ var durationProbes = new[]
+ {
+ new MockDurationProbe("Any Other Timer"),
+ };
+
+ sut.Observe(new ProbeContext(durationProbes, new ISignalProbe[0]));
+
+ var timeSpan = TimeSpan.FromSeconds(11);
+ var d = new DurationEvent(timeSpan, null);
+ durationProbes[0].Observers(ref d);
+
+ // asserting the number of accessed counters
+ Assert.AreEqual(2, cache.Count);
+
+ var counter1 = cache.Get(new CounterInstanceName("Any Other Timer", "Sender@af016c07"));
+ var counter1average = cache.Get(new CounterInstanceName("Any Other Timer Average", "Sender@af016c07"));
+ var counter1averageBase = cache.Get(new CounterInstanceName("Any Other Timer AverageBase", "Sender@af016c07"));
+
+ Assert.AreEqual(0, counter1.RawValue);
+ Assert.AreEqual(CalculateAverageTimerCounterUpdate(timeSpan), counter1average.RawValue);
+ Assert.AreEqual(1, counter1averageBase.RawValue);
+ }
+
+ static long CalculateAverageTimerCounterUpdate(TimeSpan d)
+ {
+ return d.Ticks * Stopwatch.Frequency / TimeSpan.TicksPerSecond;
+ }
+ [Test]
+ public async Task Durations_should_be_reported_as_zeros_after_specific_period_from_last_observed_pipeline_completion()
{
+ const string endpoint = "Sender@af016c07";
var resetTimersAfter = TimeSpan.FromMilliseconds(100);
var cache = new MockPerformanceCountersCache();
- var sut = new PerformanceCounterUpdater(cache, new Dictionary(), resetTimersAfter);
+ var updater = new PerformanceCounterUpdater(cache, new Dictionary(), endpoint, resetTimersAfter);
- Thread.Sleep(TimeSpan.FromTicks(resetTimersAfter.Ticks * 2));
+ var durationProbes = new[]
+ {
+ new MockDurationProbe("Critical Time"),
+ new MockDurationProbe("Processing Time")
+ };
+
+ // update before timeout
+ updater.Observe(new ProbeContext(durationProbes, new ISignalProbe[0]));
- sut.Update(PayloadWithRandomTimers);
+ updater.Start();
- var performanceCounterOne = cache.Get(new CounterInstanceName("Critical Time", "Sender@af016c07"));
- var performanceCounterTwo = cache.Get(new CounterInstanceName("Processing Time", "Sender@af016c07"));
+ durationProbes[0].Raise(TimeSpan.FromSeconds(11));
+ durationProbes[1].Raise(TimeSpan.FromSeconds(22));
+
+ await Task.Delay(TimeSpan.FromTicks(resetTimersAfter.Ticks * 2));
+
+ var performanceCounterOne = cache.Get(new CounterInstanceName("Critical Time", endpoint));
+ var performanceCounterTwo = cache.Get(new CounterInstanceName("Processing Time", endpoint));
+
+ await updater.Stop();
Assert.AreEqual(0, performanceCounterOne.RawValue);
Assert.AreEqual(0, performanceCounterTwo.RawValue);
}
[Test]
- public void Timers_within_payload_should_be_reported_properly_after_observed_pipeline_completion()
+ public void Durations_should_be_reported_properly_after_observed_pipeline_completion()
{
+ const string endpoint = "Sender@af016c07";
var resetTimersAfter = TimeSpan.FromMilliseconds(100);
var cache = new MockPerformanceCountersCache();
- var sut = new PerformanceCounterUpdater(cache, new Dictionary(), resetTimersAfter);
+ var updater = new PerformanceCounterUpdater(cache, new Dictionary(), endpoint, resetTimersAfter);
+
+ var durationProbes = new[]
+ {
+ new MockDurationProbe("Critical Time"),
+ new MockDurationProbe("Processing Time")
+ };
+
+ // update before timeout
+ updater.Observe(new ProbeContext(durationProbes, new ISignalProbe[0]));
+
+ updater.Start();
Thread.Sleep(TimeSpan.FromTicks(resetTimersAfter.Ticks * 2));
- sut.OnReceivePipelineCompleted();
+ updater.OnReceivePipelineCompleted();
- sut.Update(PayloadWithRandomTimers);
+ durationProbes[0].Raise(TimeSpan.FromSeconds(11));
+ durationProbes[1].Raise(TimeSpan.FromSeconds(22));
- var performanceCounterOne = cache.Get(new CounterInstanceName("Critical Time", "Sender@af016c07"));
- var performanceCounterTwo = cache.Get(new CounterInstanceName("Processing Time", "Sender@af016c07"));
+ var performanceCounterOne = cache.Get(new CounterInstanceName("Critical Time", endpoint));
+ var performanceCounterTwo = cache.Get(new CounterInstanceName("Processing Time", endpoint));
Assert.AreEqual(11, performanceCounterOne.RawValue);
Assert.AreEqual(22, performanceCounterTwo.RawValue);
@@ -245,5 +233,47 @@ protected override IPerformanceCounterInstance CreateInstance(CounterInstanceNam
{
return new MockIPerformanceCounter();
}
+
+ public int Count => CountCounters();
+ }
+
+ class MockSignalProbe : ISignalProbe
+ {
+ public MockSignalProbe(string name)
+ {
+ Name = name;
+ }
+
+ public void Register(OnEvent observer)
+ {
+ Observers += observer;
+ }
+
+ public string Name { get; }
+ public string Description => string.Empty;
+ public OnEvent Observers = (ref SignalEvent e) => { };
+ }
+
+ class MockDurationProbe : IDurationProbe
+ {
+ public MockDurationProbe(string name)
+ {
+ Name = name;
+ }
+
+ public void Register(OnEvent observer)
+ {
+ Observers += observer;
+ }
+
+ public void Raise(TimeSpan timespan, string messageType = null)
+ {
+ var duration = new DurationEvent(timespan, messageType);
+ Observers(ref duration);
+ }
+
+ public string Name { get; }
+ public string Description => string.Empty;
+ public OnEvent Observers = (ref DurationEvent d) => { };
}
}
\ No newline at end of file
diff --git a/src/NServiceBus.Metrics.PerformanceCounters.Tests/PerformanceCountersCacheTests.Should_throw_for_endpoint_name_too_long.approved.txt b/src/NServiceBus.Metrics.PerformanceCounters.Tests/PerformanceCountersCacheTests.Should_throw_for_endpoint_name_too_long.approved.txt
index 25d7cb5..85a2ab6 100644
--- a/src/NServiceBus.Metrics.PerformanceCounters.Tests/PerformanceCountersCacheTests.Should_throw_for_endpoint_name_too_long.approved.txt
+++ b/src/NServiceBus.Metrics.PerformanceCounters.Tests/PerformanceCountersCacheTests.Should_throw_for_endpoint_name_too_long.approved.txt
@@ -1 +1 @@
-The endpoint name ('*********************************************************************************************************************************') is too long (longer then 127) to register as a performance counter instance name. Reduce the endpoint name.
\ No newline at end of file
+The endpoint name ('*********************************************************************************************************************************') is too long (longer then 127) to register as a performance counter instance name. Shorten the endpoint name length.
\ No newline at end of file
diff --git a/src/NServiceBus.Metrics.PerformanceCounters.Tests/PerformanceCountersCacheTests.cs b/src/NServiceBus.Metrics.PerformanceCounters.Tests/PerformanceCountersCacheTests.cs
index dc0988c..4f60324 100644
--- a/src/NServiceBus.Metrics.PerformanceCounters.Tests/PerformanceCountersCacheTests.cs
+++ b/src/NServiceBus.Metrics.PerformanceCounters.Tests/PerformanceCountersCacheTests.cs
@@ -1,6 +1,7 @@
namespace Tests
{
using System;
+ using System.Runtime.CompilerServices;
using ApprovalTests;
using NUnit.Framework;
@@ -25,6 +26,7 @@ public void Get_the_same_counter_twice_returns_the_same()
}
[Test]
+ [MethodImpl(MethodImplOptions.NoInlining)]
public void Should_throw_for_endpoint_name_too_long()
{
var cache = new PerformanceCountersCache();
diff --git a/src/NServiceBus.Metrics.PerformanceCounters.Tests/PipelineExtensionsTests.cs b/src/NServiceBus.Metrics.PerformanceCounters.Tests/PipelineExtensionsTests.cs
index 55b1ded..1b91500 100644
--- a/src/NServiceBus.Metrics.PerformanceCounters.Tests/PipelineExtensionsTests.cs
+++ b/src/NServiceBus.Metrics.PerformanceCounters.Tests/PipelineExtensionsTests.cs
@@ -8,7 +8,7 @@ public class PipelineExtensionsTests
{
[Test]
- public void Should_extract_timesent_from_headers()
+ public void Should_extract_timeSent_from_headers()
{
var dateTime = new DateTime(2000, 1, 1, 1, 1, 1, DateTimeKind.Utc);
var headers = new Dictionary
@@ -22,8 +22,7 @@ public void Should_extract_timesent_from_headers()
startedAt: new DateTime(2000, 1, 1, 1, 1, 2, DateTimeKind.Utc),
completedAt: new DateTime(2000, 1, 1, 1, 1, 3, DateTimeKind.Utc));
- DateTime timeSent;
- pipelineCompleted.TryGetTimeSent(out timeSent);
+ pipelineCompleted.TryGetTimeSent(out var timeSent);
Assert.AreEqual(dateTime, timeSent);
}
}
\ No newline at end of file
diff --git a/src/NServiceBus.Metrics.PerformanceCounters.Tests/packages.config b/src/NServiceBus.Metrics.PerformanceCounters.Tests/packages.config
deleted file mode 100644
index d175419..0000000
--- a/src/NServiceBus.Metrics.PerformanceCounters.Tests/packages.config
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/NServiceBus.Metrics.PerformanceCounters.sln b/src/NServiceBus.Metrics.PerformanceCounters.sln
index a2f41ea..e86d426 100644
--- a/src/NServiceBus.Metrics.PerformanceCounters.sln
+++ b/src/NServiceBus.Metrics.PerformanceCounters.sln
@@ -1,25 +1,21 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
-VisualStudioVersion = 15.0.26403.3
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NServiceBus.Metrics.PerformanceCounters", "NServiceBus.Metrics.PerformanceCounters\NServiceBus.Metrics.PerformanceCounters.csproj", "{DF381B87-8EB9-4F30-9E92-0849641ED01A}"
+VisualStudioVersion = 15.0.27004.2002
+MinimumVisualStudioVersion = 15.0.26403.3
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NServiceBus.Metrics.PerformanceCounters", "NServiceBus.Metrics.PerformanceCounters\NServiceBus.Metrics.PerformanceCounters.csproj", "{DF381B87-8EB9-4F30-9E92-0849641ED01A}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NServiceBus.Metrics.PerformanceCounters.Tests", "NServiceBus.Metrics.PerformanceCounters.Tests\NServiceBus.Metrics.PerformanceCounters.Tests.csproj", "{9BCDA27A-5FC2-4197-9DCF-0D0F70424B58}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NServiceBus.Metrics.PerformanceCounters.Tests", "NServiceBus.Metrics.PerformanceCounters.Tests\NServiceBus.Metrics.PerformanceCounters.Tests.csproj", "{9BCDA27A-5FC2-4197-9DCF-0D0F70424B58}"
EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{54D85933-AF31-49D3-9208-36DC4689B291}"
- ProjectSection(SolutionItems) = preProject
- ..\packaging\nuget\NServiceBus.Metrics.PerformanceCounters.MsBuild.nuspec = ..\packaging\nuget\NServiceBus.Metrics.PerformanceCounters.MsBuild.nuspec
- ..\packaging\nuget\NServiceBus.Metrics.PerformanceCounters.MsBuild.targets = ..\packaging\nuget\NServiceBus.Metrics.PerformanceCounters.MsBuild.targets
- ..\packaging\nuget\NServiceBus.Metrics.PerformanceCounters.nuspec = ..\packaging\nuget\NServiceBus.Metrics.PerformanceCounters.nuspec
- nuget.config = nuget.config
- EndProjectSection
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ScriptBuilderTask", "ScriptBuilderTask\ScriptBuilderTask.csproj", "{08FD76CB-6988-485A-A535-B3129AF89C60}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ScriptBuilderTask", "ScriptBuilderTask\ScriptBuilderTask.csproj", "{08FD76CB-6988-485A-A535-B3129AF89C60}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ScriptBuilder", "ScriptBuilder\ScriptBuilder.csproj", "{1BDA0A75-91F6-4412-A780-7BE9322B2A4E}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ScriptBuilderTask.Tests", "ScriptBuilderTask.Tests\ScriptBuilderTask.Tests.csproj", "{8174164E-52B8-4878-BFB0-34C81A31930E}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ScriptBuilderTask.Tests", "ScriptBuilderTask.Tests\ScriptBuilderTask.Tests.csproj", "{8174164E-52B8-4878-BFB0-34C81A31930E}"
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{1B573EC5-07D6-4E25-9687-FB5A536B4FD9}"
+ ProjectSection(SolutionItems) = preProject
+ Directory.Build.props = Directory.Build.props
+ ..\GitVersion.yml = ..\GitVersion.yml
+ EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -39,10 +35,6 @@ Global
{08FD76CB-6988-485A-A535-B3129AF89C60}.Debug|Any CPU.Build.0 = Debug|Any CPU
{08FD76CB-6988-485A-A535-B3129AF89C60}.Release|Any CPU.ActiveCfg = Release|Any CPU
{08FD76CB-6988-485A-A535-B3129AF89C60}.Release|Any CPU.Build.0 = Release|Any CPU
- {1BDA0A75-91F6-4412-A780-7BE9322B2A4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {1BDA0A75-91F6-4412-A780-7BE9322B2A4E}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {1BDA0A75-91F6-4412-A780-7BE9322B2A4E}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {1BDA0A75-91F6-4412-A780-7BE9322B2A4E}.Release|Any CPU.Build.0 = Release|Any CPU
{8174164E-52B8-4878-BFB0-34C81A31930E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8174164E-52B8-4878-BFB0-34C81A31930E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8174164E-52B8-4878-BFB0-34C81A31930E}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -51,4 +43,7 @@ Global
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {021BB233-292E-4506-90FA-B10BD9F3F80D}
+ EndGlobalSection
EndGlobal
diff --git a/src/NServiceBus.Metrics.PerformanceCounters.sln.DotSettings b/src/NServiceBus.Metrics.PerformanceCounters.sln.DotSettings
index 4e4965d..611eecc 100644
--- a/src/NServiceBus.Metrics.PerformanceCounters.sln.DotSettings
+++ b/src/NServiceBus.Metrics.PerformanceCounters.sln.DotSettings
@@ -1,13 +1,17 @@
- CSharp60
+ Experimental
+ DO_NOT_SHOW
+ ERROR
+ ERROR
+ ERROR
True
True
True
False
True
- ExplicitlyExcluded
+ ExplicitlyExcluded
SOLUTION
SUGGESTION
SUGGESTION
@@ -23,6 +27,7 @@
ERROR
ERROR
ERROR
+ DO_NOT_SHOW
DO_NOT_SHOW
DO_NOT_SHOW
DO_NOT_SHOW
@@ -45,6 +50,13 @@
ERROR
ERROR
ERROR
+ ERROR
+ ERROR
+ ERROR
+ ERROR
+ ERROR
+ ERROR
+ ERROR
ERROR
ERROR
DO_NOT_SHOW
@@ -112,6 +124,7 @@
DoHide
DoHide
DoHide
+ WARNING
ERROR
ERROR
ERROR
@@ -134,11 +147,13 @@
HINT
WARNING
ERROR
- ERROR
- ERROR
<?xml version="1.0" encoding="utf-16"?><Profile name="Format My Code Using "Particular" conventions"><CSMakeFieldReadonly>True</CSMakeFieldReadonly><CSUseVar><BehavourStyle>CAN_CHANGE_TO_IMPLICIT</BehavourStyle><LocalVariableStyle>ALWAYS_IMPLICIT</LocalVariableStyle><ForeachVariableStyle>ALWAYS_IMPLICIT</ForeachVariableStyle></CSUseVar><CSOptimizeUsings><OptimizeUsings>True</OptimizeUsings><EmbraceInRegion>False</EmbraceInRegion><RegionName></RegionName></CSOptimizeUsings><CSReformatCode>True</CSReformatCode><CSReorderTypeMembers>True</CSReorderTypeMembers><JsInsertSemicolon>True</JsInsertSemicolon><JsReformatCode>True</JsReformatCode><CssReformatCode>True</CssReformatCode><CSArrangeThisQualifier>True</CSArrangeThisQualifier><RemoveCodeRedundancies>True</RemoveCodeRedundancies><CSUseAutoProperty>True</CSUseAutoProperty><HtmlReformatCode>True</HtmlReformatCode><CSShortenReferences>True</CSShortenReferences><CSharpFormatDocComments>True</CSharpFormatDocComments><CssAlphabetizeProperties>True</CssAlphabetizeProperties></Profile>
Default: Reformat Code
Format My Code Using "Particular" conventions
+ Required
+ Required
+ Required
+ Required
Implicit
Implicit
False
@@ -148,6 +163,7 @@
ALWAYS_ADD
ALWAYS_ADD
ALWAYS_ADD
+ False
False
False
False
@@ -155,8 +171,6 @@
False
CHOP_ALWAYS
CHOP_ALWAYS
- True
- True
ZeroIndent
ZeroIndent
<?xml version="1.0" encoding="utf-16"?>
@@ -535,53 +549,6 @@ II.2.12 <HandlesEvent />
<Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
<Policy Inspect="True" Prefix="T" Suffix="" Style="AaBb" />
<Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
- <Policy Inspect="True" Prefix="I" Suffix="" Style="AaBb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
- <Policy Inspect="True" Prefix="T" Suffix="" Style="AaBb" />
- $object$_On$event$
- <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
- <Policy Inspect="True" Prefix="I" Suffix="" Style="AaBb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
- <Policy Inspect="True" Prefix="T" Suffix="" Style="AaBb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
<Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
<Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
<Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
@@ -594,12 +561,8 @@ II.2.12 <HandlesEvent />
True
True
True
- True
- True
- True
True
-
<data />
<data><IncludeFilters /><ExcludeFilters /></data>
\ No newline at end of file
diff --git a/src/NServiceBus.Metrics.PerformanceCounters/AssemblyInfo.cs b/src/NServiceBus.Metrics.PerformanceCounters/AssemblyInfo.cs
deleted file mode 100644
index 2bcda94..0000000
--- a/src/NServiceBus.Metrics.PerformanceCounters/AssemblyInfo.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-using System;
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-[assembly: AssemblyTitle("NServiceBus.Metrics.PerformanceCounters")]
-[assembly: AssemblyCopyright("Copyright NServiceBus Ltd. All rights reserved")]
-[assembly: AssemblyProduct("NServiceBus.Metrics.PerformanceCounters")]
-[assembly: AssemblyCompany("NServiceBus Ltd.")]
-[assembly: ComVisible(false)]
-[assembly: CLSCompliant(true)]
-[assembly: InternalsVisibleTo("Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100D32BC524DCB1205998C155A4F36BF873587D3602822ECD7B49CD775B2E6A006EE6B9164AB2E3103A6A4D1310C6E5C26818A32FE86710141A2D1F02EB564381CD64C88131BCCA478CDB5072F06DB991DE33DAC1C82BAF40D9F61DD6B40300A4673B693B51CD10A8B9B7D8AB64450431FA422514D6DABCAF70DF785B1E4E6E8AAF")]
\ No newline at end of file
diff --git a/src/NServiceBus.Metrics.PerformanceCounters/CounterInstanceName.cs b/src/NServiceBus.Metrics.PerformanceCounters/CounterInstanceName.cs
index 6db13dd..60268a3 100644
--- a/src/NServiceBus.Metrics.PerformanceCounters/CounterInstanceName.cs
+++ b/src/NServiceBus.Metrics.PerformanceCounters/CounterInstanceName.cs
@@ -9,8 +9,16 @@ public bool Equals(CounterInstanceName other)
public override bool Equals(object obj)
{
- if (ReferenceEquals(null, obj)) return false;
- return obj is CounterInstanceName && Equals((CounterInstanceName)obj);
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (!(obj is CounterInstanceName))
+ {
+ return false;
+ }
+ return Equals((CounterInstanceName)obj);
}
public override int GetHashCode()
diff --git a/src/NServiceBus.Metrics.PerformanceCounters/Counters/IPerformanceCounterInstance.cs b/src/NServiceBus.Metrics.PerformanceCounters/Counters/IPerformanceCounterInstance.cs
index 92b9ca8..1fbdc74 100644
--- a/src/NServiceBus.Metrics.PerformanceCounters/Counters/IPerformanceCounterInstance.cs
+++ b/src/NServiceBus.Metrics.PerformanceCounters/Counters/IPerformanceCounterInstance.cs
@@ -3,5 +3,6 @@
interface IPerformanceCounterInstance : IDisposable
{
void Increment();
+ void IncrementBy(long value);
long RawValue { get; set; }
}
\ No newline at end of file
diff --git a/src/NServiceBus.Metrics.PerformanceCounters/Counters/PerformanceCounterInstance.cs b/src/NServiceBus.Metrics.PerformanceCounters/Counters/PerformanceCounterInstance.cs
index 638266f..c1827c7 100644
--- a/src/NServiceBus.Metrics.PerformanceCounters/Counters/PerformanceCounterInstance.cs
+++ b/src/NServiceBus.Metrics.PerformanceCounters/Counters/PerformanceCounterInstance.cs
@@ -12,6 +12,11 @@ public void Increment()
counter.Increment();
}
+ public void IncrementBy(long value)
+ {
+ counter.IncrementBy(value);
+ }
+
public void Dispose()
{
counter?.Dispose();
@@ -21,7 +26,7 @@ public void Dispose()
public long RawValue
{
- get { return counter.RawValue; }
- set { counter.RawValue = value; }
+ get => counter.RawValue;
+ set => counter.RawValue = value;
}
}
\ No newline at end of file
diff --git a/src/NServiceBus.Metrics.PerformanceCounters/Counters/PerformanceCountersCache.cs b/src/NServiceBus.Metrics.PerformanceCounters/Counters/PerformanceCountersCache.cs
index 1eeb7ee..a5b2b96 100644
--- a/src/NServiceBus.Metrics.PerformanceCounters/Counters/PerformanceCountersCache.cs
+++ b/src/NServiceBus.Metrics.PerformanceCounters/Counters/PerformanceCountersCache.cs
@@ -27,7 +27,7 @@ protected virtual IPerformanceCounterInstance CreateInstance(CounterInstanceName
if (counterInstanceName.InstanceName.Length > sbyte.MaxValue)
{
- throw new Exception($"The endpoint name ('{counterInstanceName.InstanceName}') is too long (longer then {sbyte.MaxValue}) to register as a performance counter instance name. Reduce the endpoint name.");
+ throw new Exception($"The endpoint name ('{counterInstanceName.InstanceName}') is too long (longer then {sbyte.MaxValue}) to register as a performance counter instance name. Shorten the endpoint name length.");
}
try
@@ -42,5 +42,7 @@ protected virtual IPerformanceCounterInstance CreateInstance(CounterInstanceName
return new PerformanceCounterInstance(counter);
}
+ protected int CountCounters() => counterCache.Count;
+
ConcurrentDictionary counterCache = new ConcurrentDictionary();
-}
\ No newline at end of file
+}
diff --git a/src/NServiceBus.Metrics.PerformanceCounters/Extensions.cs b/src/NServiceBus.Metrics.PerformanceCounters/Extensions.cs
index fe60015..45628bb 100644
--- a/src/NServiceBus.Metrics.PerformanceCounters/Extensions.cs
+++ b/src/NServiceBus.Metrics.PerformanceCounters/Extensions.cs
@@ -7,8 +7,7 @@ static class Extensions
public static bool TryGetTimeSent(this ReceivePipelineCompleted completed, out DateTime timeSent)
{
var headers = completed.ProcessedMessage.Headers;
- string timeSentString;
- if (headers.TryGetValue(Headers.TimeSent, out timeSentString))
+ if (headers.TryGetValue(Headers.TimeSent, out var timeSentString))
{
timeSent = DateTimeExtensions.ToUtcDateTime(timeSentString);
return true;
@@ -17,7 +16,7 @@ public static bool TryGetTimeSent(this ReceivePipelineCompleted completed, out D
return false;
}
- public static void ThrowIfSendonly(this FeatureConfigurationContext context)
+ public static void ThrowIfSendOnly(this FeatureConfigurationContext context)
{
var isSendOnly = context.Settings.GetOrDefault("Endpoint.SendOnly");
if (isSendOnly)
diff --git a/src/NServiceBus.Metrics.PerformanceCounters/FodyWeavers.xml b/src/NServiceBus.Metrics.PerformanceCounters/FodyWeavers.xml
new file mode 100644
index 0000000..4f63d3b
--- /dev/null
+++ b/src/NServiceBus.Metrics.PerformanceCounters/FodyWeavers.xml
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/src/NServiceBus.Metrics.PerformanceCounters/InternalsVisibleTo.cs b/src/NServiceBus.Metrics.PerformanceCounters/InternalsVisibleTo.cs
new file mode 100644
index 0000000..0a2b32e
--- /dev/null
+++ b/src/NServiceBus.Metrics.PerformanceCounters/InternalsVisibleTo.cs
@@ -0,0 +1,3 @@
+using System.Runtime.CompilerServices;
+
+[assembly: InternalsVisibleTo("NServiceBus.Metrics.PerformanceCounters.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100D32BC524DCB1205998C155A4F36BF873587D3602822ECD7B49CD775B2E6A006EE6B9164AB2E3103A6A4D1310C6E5C26818A32FE86710141A2D1F02EB564381CD64C88131BCCA478CDB5072F06DB991DE33DAC1C82BAF40D9F61DD6B40300A4673B693B51CD10A8B9B7D8AB64450431FA422514D6DABCAF70DF785B1E4E6E8AAF")]
\ No newline at end of file
diff --git a/src/NServiceBus.Metrics.PerformanceCounters/Meter.cs b/src/NServiceBus.Metrics.PerformanceCounters/Meter.cs
deleted file mode 100644
index 61ecd9d..0000000
--- a/src/NServiceBus.Metrics.PerformanceCounters/Meter.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-struct Meter
-{
- public readonly string Name;
- public readonly long Count;
-
- public Meter(string name, long count)
- {
- Name = name;
- Count = count;
- }
-}
\ No newline at end of file
diff --git a/src/NServiceBus.Metrics.PerformanceCounters/NServiceBus.Metrics.PerformanceCounters.csproj b/src/NServiceBus.Metrics.PerformanceCounters/NServiceBus.Metrics.PerformanceCounters.csproj
index 362401c..dd60200 100644
--- a/src/NServiceBus.Metrics.PerformanceCounters/NServiceBus.Metrics.PerformanceCounters.csproj
+++ b/src/NServiceBus.Metrics.PerformanceCounters/NServiceBus.Metrics.PerformanceCounters.csproj
@@ -1,114 +1,28 @@
-
-
-
+
+
- Debug
- AnyCPU
- {DF381B87-8EB9-4F30-9E92-0849641ED01A}
- Library
- Properties
- NServiceBus.Metrics.PerformanceCounters
- NServiceBus.Metrics.PerformanceCounters
- v4.5.2
- 512
+ net452
true
- ..\NServiceBus.snk
-
-
-
-
- true
- full
- false
- ..\..\binaries\
- DEBUG;TRACE
- prompt
- 4
- true
- ..\..\binaries\NServiceBus.Metrics.PerformanceCounters.xml
-
-
-
-
- pdbonly
- true
+ $(SolutionDir)NServiceBus.snk
..\..\binaries\
- TRACE
- prompt
- 4
- true
- ..\..\binaries\NServiceBus.Metrics.PerformanceCounters.xml
-
-
+ Enables access to performance counters
+
-
- ..\packages\Newtonsoft.Json.10.0.2\lib\net45\Newtonsoft.Json.dll
-
-
- ..\packages\NServiceBus.6.3.4\lib\net452\NServiceBus.Core.dll
-
-
- ..\packages\NServiceBus.Metrics.1.0.1\lib\net452\NServiceBus.Metrics.dll
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
- Designer
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
-
-
-
-
-
+
\ No newline at end of file
diff --git a/src/NServiceBus.Metrics.PerformanceCounters/NServiceBus.Metrics.PerformanceCounters.csproj.DotSettings b/src/NServiceBus.Metrics.PerformanceCounters/NServiceBus.Metrics.PerformanceCounters.csproj.DotSettings
deleted file mode 100644
index 3fdbc3c..0000000
--- a/src/NServiceBus.Metrics.PerformanceCounters/NServiceBus.Metrics.PerformanceCounters.csproj.DotSettings
+++ /dev/null
@@ -1,2 +0,0 @@
-
- True
\ No newline at end of file
diff --git a/src/NServiceBus.Metrics.PerformanceCounters/PerformanceCounterSettingsAttribute.cs b/src/NServiceBus.Metrics.PerformanceCounters/PerformanceCounterSettingsAttribute.cs
index 5e8c044..8ef822b 100644
--- a/src/NServiceBus.Metrics.PerformanceCounters/PerformanceCounterSettingsAttribute.cs
+++ b/src/NServiceBus.Metrics.PerformanceCounters/PerformanceCounterSettingsAttribute.cs
@@ -23,7 +23,7 @@ public sealed class PerformanceCounterSettingsAttribute : Attribute
///
/// Path to promote performance counter installation scripts to.
/// The token '$(SolutionDir)' will be replace with the current solution directory.
- /// The token '$(ProjectDir)' will be replace witht he current solution directory.
+ /// The token '$(ProjectDir)' will be replace with the current solution directory.
/// The path calculation is performed relative to the current project directory.
///
public string ScriptPromotionPath { get; set; }
diff --git a/src/NServiceBus.Metrics.PerformanceCounters/PerformanceCounterUpdater.cs b/src/NServiceBus.Metrics.PerformanceCounters/PerformanceCounterUpdater.cs
index 77ed25f..21dc58c 100644
--- a/src/NServiceBus.Metrics.PerformanceCounters/PerformanceCounterUpdater.cs
+++ b/src/NServiceBus.Metrics.PerformanceCounters/PerformanceCounterUpdater.cs
@@ -1,54 +1,72 @@
using System;
+using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;
-using Newtonsoft.Json.Linq;
+using System.Diagnostics;
+using System.Threading.Tasks;
+using NServiceBus;
+using NServiceBus.Metrics.PerformanceCounters;
class PerformanceCounterUpdater
{
- public PerformanceCounterUpdater(PerformanceCountersCache cache, Dictionary legacyInstanceNameMap, TimeSpan? resetTimersAfter = null)
+ public PerformanceCounterUpdater(PerformanceCountersCache cache, Dictionary legacyInstanceNameMap, string endpointName, TimeSpan? resetTimersAfter = null)
{
- resetAfterTicks = (resetTimersAfter ?? TimeSpan.FromSeconds(2)).Ticks;
+ resetEvery = resetTimersAfter ?? TimeSpan.FromSeconds(2);
this.legacyInstanceNameMap = legacyInstanceNameMap;
+ this.endpointName = endpointName;
this.cache = cache;
-
+ cancellation = new CancellationTokenSource();
// initialize to an armed state
OnReceivePipelineCompleted();
}
- public void Update(string payload)
+ public void Start()
+ {
+ cleaner = Task.Run(Cleanup);
+ }
+
+ public Task Stop()
{
- var rootObject = JObject.Parse(payload);
+ cancellation.Cancel();
+ return cleaner;
+ }
- var context = rootObject.Value("Context");
- var meters = rootObject["Meters"]?.ToObject>() ?? new List();
- foreach (var meter in meters)
+ public void Observe(ProbeContext context)
+ {
+ foreach (var signalProbe in context.Signals)
{
- CounterInstanceName? instanceName;
- legacyInstanceNameMap.TryGetValue(meter.Name, out instanceName);
+ legacyInstanceNameMap.TryGetValue(signalProbe.Name, out var instanceName);
- var performanceCounterInstance = cache.Get(instanceName ?? new CounterInstanceName(meter.Name, context));
- performanceCounterInstance.RawValue = meter.Count;
+ var performanceCounterInstance = cache.Get(instanceName ?? new CounterInstanceName(signalProbe.Name, endpointName));
+
+ signalProbe.Register((ref SignalEvent e) => performanceCounterInstance.Increment());
}
- var timers = rootObject["Timers"]?.ToObject>() ?? new List();
- foreach (var timer in timers)
+ foreach (var durationProbe in context.Durations)
{
- var performanceCounterInstance = cache.Get(new CounterInstanceName(timer.Name, context));
-
- var idleFor = NowTicks - Volatile.Read(ref lastCompleted);
- if (idleFor > resetAfterTicks)
+ if (durationProbe.Name == CounterNameConventions.ProcessingTime || durationProbe.Name == CounterNameConventions.CriticalTime)
{
- performanceCounterInstance.RawValue = 0;
+ var key = new CounterInstanceName(durationProbe.Name, endpointName);
+ var performanceCounterInstance = cache.Get(key);
+ resettable[key] = performanceCounterInstance;
+ durationProbe.Register((ref DurationEvent d) => performanceCounterInstance.RawValue = (long) d.Duration.TotalSeconds);
}
- else
+
+ var averageTimerCounter = cache.Get(new CounterInstanceName(durationProbe.Name.GetAverageTimerCounterName(), endpointName));
+ var baseAverageTimerCounter = cache.Get(new CounterInstanceName(durationProbe.Name.GetAverageTimerBaseCounterName(), endpointName));
+
+ durationProbe.Register((ref DurationEvent d) =>
{
- performanceCounterInstance.RawValue = timer.Histogram.LastValue / 1000;
- }
+ var performanceCounterTicks = d.Duration.Ticks * Stopwatch.Frequency / TimeSpan.TicksPerSecond;
+ averageTimerCounter.IncrementBy(performanceCounterTicks);
+ baseAverageTimerCounter.Increment();
+ });
}
}
readonly PerformanceCountersCache cache;
readonly Dictionary legacyInstanceNameMap;
+ readonly ConcurrentDictionary resettable = new ConcurrentDictionary();
long lastCompleted;
public void OnReceivePipelineCompleted()
@@ -56,6 +74,26 @@ public void OnReceivePipelineCompleted()
Volatile.Write(ref lastCompleted, NowTicks);
}
+ async Task Cleanup()
+ {
+ while (cancellation.IsCancellationRequested == false)
+ {
+ await Task.Delay(resetEvery).ConfigureAwait(false);
+
+ var idleFor = NowTicks - Volatile.Read(ref lastCompleted);
+ if (idleFor > resetEvery.Ticks)
+ {
+ foreach (var performanceCounter in resettable)
+ {
+ performanceCounter.Value.RawValue = 0;
+ }
+ }
+ }
+ }
+
static long NowTicks => DateTime.UtcNow.Ticks;
- readonly long resetAfterTicks;
+ readonly TimeSpan resetEvery;
+ readonly string endpointName;
+ Task cleaner;
+ readonly CancellationTokenSource cancellation;
}
\ No newline at end of file
diff --git a/src/NServiceBus.Metrics.PerformanceCounters/PerformanceCountersExtensions.cs b/src/NServiceBus.Metrics.PerformanceCounters/PerformanceCountersExtensions.cs
index 5fd7280..e2c8197 100644
--- a/src/NServiceBus.Metrics.PerformanceCounters/PerformanceCountersExtensions.cs
+++ b/src/NServiceBus.Metrics.PerformanceCounters/PerformanceCountersExtensions.cs
@@ -14,9 +14,6 @@ public static PerformanceCountersSettings EnableWindowsPerformanceCounters(this
{
Guard.AgainstNull(nameof(endpointConfiguration), endpointConfiguration);
-#pragma warning disable 618
- endpointConfiguration.DisableFeature();
-#pragma warning restore 618
endpointConfiguration.EnableFeature();
return new PerformanceCountersSettings(endpointConfiguration);
diff --git a/src/NServiceBus.Metrics.PerformanceCounters/PerformanceCountersFeature.cs b/src/NServiceBus.Metrics.PerformanceCounters/PerformanceCountersFeature.cs
index cbc69e9..30855d0 100644
--- a/src/NServiceBus.Metrics.PerformanceCounters/PerformanceCountersFeature.cs
+++ b/src/NServiceBus.Metrics.PerformanceCounters/PerformanceCountersFeature.cs
@@ -11,23 +11,22 @@ public PerformanceCountersFeature()
Defaults(s =>
{
options = s.EnableMetrics();
- s.SetDefault(UpdateIntervalKey, TimeSpan.FromSeconds(2));
});
}
protected override void Setup(FeatureConfigurationContext context)
{
- var logicalAddress = context.Settings.LogicalAddress();
+ var endpoint = context.Settings.LogicalAddress().EndpointInstance.Endpoint;
var legacyInstanceNameMap = new Dictionary
{
- {"# of message failures / sec", new CounterInstanceName(MessagesFailuresPerSecondCounterName, logicalAddress.EndpointInstance.Endpoint)},
- {"# of messages pulled from the input queue / sec", new CounterInstanceName(MessagesPulledPerSecondCounterName, logicalAddress.EndpointInstance.Endpoint)},
- {"# of messages successfully processed / sec", new CounterInstanceName(MessagesProcessedPerSecondCounterName, logicalAddress.EndpointInstance.Endpoint)}
+ {"# of message failures / sec", new CounterInstanceName(MessagesFailuresPerSecondCounterName, endpoint)},
+ {"# of messages pulled from the input queue / sec", new CounterInstanceName(MessagesPulledPerSecondCounterName, endpoint)},
+ {"# of messages successfully processed / sec", new CounterInstanceName(MessagesProcessedPerSecondCounterName, endpoint)}
};
cache = new PerformanceCountersCache();
- updater = new PerformanceCounterUpdater(cache, legacyInstanceNameMap);
+ updater = new PerformanceCounterUpdater(cache, legacyInstanceNameMap, endpoint);
context.RegisterStartupTask(new Cleanup(this));
@@ -37,11 +36,10 @@ protected override void Setup(FeatureConfigurationContext context)
return TaskExtensions.CompletedTask;
});
- options.EnableCustomReport(payload =>
+ options.RegisterObservers(probeContext =>
{
- updater?.Update(payload);
- return TaskExtensions.CompletedTask;
- }, context.Settings.Get(UpdateIntervalKey));
+ updater.Observe(probeContext);
+ });
}
MetricsOptions options;
@@ -53,7 +51,6 @@ protected override void Setup(FeatureConfigurationContext context)
public const string MessagesFailuresPerSecondCounterName = "# of msgs failures / sec";
public const string CriticalTimeCounterName = "Critical Time";
public const string ProcessingTimeCounterName = "Processing Time";
- public const string UpdateIntervalKey = "PerformanceCounterUpdateInterval";
class Cleanup : FeatureStartupTask, IDisposable
{
@@ -70,12 +67,13 @@ public void Dispose()
protected override Task OnStart(IMessageSession session)
{
+ feature.updater.Start();
return TaskExtensions.CompletedTask;
}
protected override Task OnStop(IMessageSession session)
{
- return TaskExtensions.CompletedTask;
+ return feature.updater.Stop();
}
PerformanceCountersFeature feature;
diff --git a/src/NServiceBus.Metrics.PerformanceCounters/PerformanceCountersSettings.cs b/src/NServiceBus.Metrics.PerformanceCounters/PerformanceCountersSettings.cs
index a19415c..27b5e95 100644
--- a/src/NServiceBus.Metrics.PerformanceCounters/PerformanceCountersSettings.cs
+++ b/src/NServiceBus.Metrics.PerformanceCounters/PerformanceCountersSettings.cs
@@ -28,14 +28,12 @@ public void EnableSLAPerformanceCounters(TimeSpan sla)
}
///
- /// Defines the update interval for the performance counter values.
+ /// Sets the update interval.
///
- /// The update interval.
+ ///
+ [ObsoleteEx(Message = "This interval is no longer used for reporting. Counters values are updated as soon as they are reported", RemoveInVersion = "3.0")]
public void UpdateCounterEvery(TimeSpan updateInterval)
{
- Guard.AgainstNegativeAndZero(nameof(updateInterval), updateInterval);
-
- endpointConfiguration.GetSettings().Set(PerformanceCountersFeature.UpdateIntervalKey, updateInterval);
}
}
}
\ No newline at end of file
diff --git a/src/NServiceBus.Metrics.PerformanceCounters/SLA/EstimatedTimeToSLABreachCounter.cs b/src/NServiceBus.Metrics.PerformanceCounters/SLA/EstimatedTimeToSLABreachCounter.cs
index 09dc358..29abf07 100644
--- a/src/NServiceBus.Metrics.PerformanceCounters/SLA/EstimatedTimeToSLABreachCounter.cs
+++ b/src/NServiceBus.Metrics.PerformanceCounters/SLA/EstimatedTimeToSLABreachCounter.cs
@@ -12,8 +12,7 @@ public EstimatedTimeToSLABreachCounter(TimeSpan endpointSla, IPerformanceCounter
public void Update(ReceivePipelineCompleted completed)
{
- DateTime timeSent;
- if (completed.TryGetTimeSent(out timeSent))
+ if (completed.TryGetTimeSent(out var timeSent))
{
Update(timeSent, completed.StartedAt, completed.CompletedAt);
}
diff --git a/src/NServiceBus.Metrics.PerformanceCounters/SLA/SLAMonitoringFeature.cs b/src/NServiceBus.Metrics.PerformanceCounters/SLA/SLAMonitoringFeature.cs
index 239b819..3a31780 100644
--- a/src/NServiceBus.Metrics.PerformanceCounters/SLA/SLAMonitoringFeature.cs
+++ b/src/NServiceBus.Metrics.PerformanceCounters/SLA/SLAMonitoringFeature.cs
@@ -7,7 +7,7 @@ class SLAMonitoringFeature : Feature
{
protected override void Setup(FeatureConfigurationContext context)
{
- context.ThrowIfSendonly();
+ context.ThrowIfSendOnly();
var settings = context.Settings;
var endpointSla = settings.Get(EndpointSLAKey);
diff --git a/src/NServiceBus.Metrics.PerformanceCounters/packages.config b/src/NServiceBus.Metrics.PerformanceCounters/packages.config
deleted file mode 100644
index 6c4fbf4..0000000
--- a/src/NServiceBus.Metrics.PerformanceCounters/packages.config
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/ScriptBuilder/AssemblyInfo.cs b/src/ScriptBuilder/AssemblyInfo.cs
deleted file mode 100644
index 14979fd..0000000
--- a/src/ScriptBuilder/AssemblyInfo.cs
+++ /dev/null
@@ -1,4 +0,0 @@
-using System.Reflection;
-
-[assembly: AssemblyTitle("NServiceBus.Metrics.PerformanceCounters.Builder")]
-[assembly: AssemblyProduct("NServiceBus.Metrics.PerformanceCounters.Builder")]
\ No newline at end of file
diff --git a/src/ScriptBuilder/ScriptBuilder.csproj b/src/ScriptBuilder/ScriptBuilder.csproj
deleted file mode 100644
index 296a452..0000000
--- a/src/ScriptBuilder/ScriptBuilder.csproj
+++ /dev/null
@@ -1,82 +0,0 @@
-
-
-
-
- Debug
- AnyCPU
- {1BDA0A75-91F6-4412-A780-7BE9322B2A4E}
- Library
- Properties
- NServiceBus.Metrics.PerformanceCounters
- NServiceBus.Metrics.PerformanceCounters.Builder
- v4.5.2
- 512
- true
- $(SolutionDir)NServiceBus.snk
-
-
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
-
-
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
-
-
-
- ..\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.dll
-
-
- ..\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.Mdb.dll
-
-
- ..\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.Pdb.dll
-
-
- ..\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.Rocks.dll
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- "$(SolutionDir)..\Tools\ilmerge.exe"
- $(ProjectDir)bin\$(ConfigurationName)\NServiceBus.Metrics.PerformanceCounters.Builder.dll
- $(ProjectDir)bin\$(ConfigurationName)\Mono.Cecil.dll
- $(SolutionDir)..\binaries\NServiceBus.Metrics.PerformanceCounters.Builder.dll
-
-
-
-
-
\ No newline at end of file
diff --git a/src/ScriptBuilder/Timers/TimerDefinitionReader.cs b/src/ScriptBuilder/Timers/TimerDefinitionReader.cs
deleted file mode 100644
index 5d1aea7..0000000
--- a/src/ScriptBuilder/Timers/TimerDefinitionReader.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-namespace NServiceBus.Metrics.PerformanceCounters
-{
- using System.Collections.Generic;
- using System.Linq;
- using Mono.Cecil;
-
- static class TimerDefinitionReader
- {
- public static bool TryGetTimerDefinition(TypeDefinition type, out List definitions)
- {
- definitions = new List();
- if (type.BaseType != null && type.BaseType.FullName == "NServiceBus.Metrics.MetricBuilder")
- {
- var timerAttributes = type.Fields.Select(f => f.GetSingleAttribute("NServiceBus.Metrics.TimerAttribute")).Where(c => c != null);
-
- foreach (var timerAttribute in timerAttributes)
- {
- var name = timerAttribute.ParameterValue("name");
- var description = timerAttribute.ParameterValue("description");
-
- definitions.Add(new TimerDefinition(name, description));
- }
- }
- return definitions.Count > 0;
- }
- }
-}
\ No newline at end of file
diff --git a/src/ScriptBuilder/packages.config b/src/ScriptBuilder/packages.config
deleted file mode 100644
index 88fbc79..0000000
--- a/src/ScriptBuilder/packages.config
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/src/ScriptBuilderTask.Tests/CSharpCodeGenerationTests.Generates.approved.cs b/src/ScriptBuilderTask.Tests/CSharpCodeGenerationTests.Generates.approved.cs
index 63382af..e22dc50 100644
--- a/src/ScriptBuilderTask.Tests/CSharpCodeGenerationTests.Generates.approved.cs
+++ b/src/ScriptBuilderTask.Tests/CSharpCodeGenerationTests.Generates.approved.cs
@@ -4,9 +4,9 @@
using System.Runtime.CompilerServices;
[CompilerGenerated]
-public static class CounterCreator
+public static class CounterCreator
{
- public static void Create()
+ public static void Create()
{
var counterCreationCollection = new CounterCreationDataCollection(Counters);
try
@@ -36,7 +36,7 @@ public static void Create()
PerformanceCounter.CloseSharedResources();
}
- catch (Exception ex) when (ex is SecurityException || ex is UnauthorizedAccessException)
+ catch (Exception ex) when(ex is SecurityException || ex is UnauthorizedAccessException)
{
throw new Exception("Execution requires elevated permissions", ex);
}
@@ -45,11 +45,16 @@ public static void Create()
static CounterCreationData[] Counters = new CounterCreationData[]
{
new CounterCreationData("SLA violation countdown", "Seconds until the SLA for this endpoint is breached.", PerformanceCounterType.NumberOfItems32),
+ new CounterCreationData("Critical Time Average", "The time it took from sending to processing the message.", PerformanceCounterType.AverageTimer32),
+ new CounterCreationData("Critical Time AverageBase", "The time it took from sending to processing the message.", PerformanceCounterType.AverageBase),
new CounterCreationData("Critical Time", "The time it took from sending to processing the message.", PerformanceCounterType.NumberOfItems32),
+ new CounterCreationData("Processing Time Average", "The time it took to successfully process a message.", PerformanceCounterType.AverageTimer32),
+ new CounterCreationData("Processing Time AverageBase", "The time it took to successfully process a message.", PerformanceCounterType.AverageBase),
new CounterCreationData("Processing Time", "The time it took to successfully process a message.", PerformanceCounterType.NumberOfItems32),
- new CounterCreationData("# of msgs pulled from the input queue /sec", "The current number of messages pulled from the input queue by the transport per second.", PerformanceCounterType.RateOfCountsPerSecond32),
new CounterCreationData("# of msgs failures / sec", "The current number of failed processed messages by the transport per second.", PerformanceCounterType.RateOfCountsPerSecond32),
new CounterCreationData("# of msgs successfully processed / sec", "The current number of messages processed successfully by the transport per second.", PerformanceCounterType.RateOfCountsPerSecond32),
+ new CounterCreationData("# of msgs pulled from the input queue /sec", "The current number of messages pulled from the input queue by the transport per second.", PerformanceCounterType.RateOfCountsPerSecond32),
+ new CounterCreationData("Retries", "A message has been scheduled for retry (FLR or SLR)", PerformanceCounterType.RateOfCountsPerSecond32),
};
}
\ No newline at end of file
diff --git a/src/ScriptBuilderTask.Tests/PowershellCodeGenerationTests.Generates.approved.ps1 b/src/ScriptBuilderTask.Tests/PowershellCodeGenerationTests.Generates.approved.ps1
index 8040fa7..53d1d67 100644
--- a/src/ScriptBuilderTask.Tests/PowershellCodeGenerationTests.Generates.approved.ps1
+++ b/src/ScriptBuilderTask.Tests/PowershellCodeGenerationTests.Generates.approved.ps1
@@ -1,3 +1,4 @@
+
#requires -RunAsAdministrator
Function InstallNSBPerfCounters {
@@ -5,15 +6,21 @@ Function InstallNSBPerfCounters {
$counters = New-Object System.Diagnostics.CounterCreationDataCollection
$counters.AddRange(@(
New-Object System.Diagnostics.CounterCreationData "SLA violation countdown", "Seconds until the SLA for this endpoint is breached.", NumberOfItems32
+ New-Object System.Diagnostics.CounterCreationData "Critical Time Average", "The time it took from sending to processing the message.", AverageTimer32
+ New-Object System.Diagnostics.CounterCreationData "Critical Time AverageBase", "The time it took from sending to processing the message.", AverageBase
New-Object System.Diagnostics.CounterCreationData "Critical Time", "The time it took from sending to processing the message.", NumberOfItems32
+ New-Object System.Diagnostics.CounterCreationData "Processing Time Average", "The time it took to successfully process a message.", AverageTimer32
+ New-Object System.Diagnostics.CounterCreationData "Processing Time AverageBase", "The time it took to successfully process a message.", AverageBase
New-Object System.Diagnostics.CounterCreationData "Processing Time", "The time it took to successfully process a message.", NumberOfItems32
- New-Object System.Diagnostics.CounterCreationData "# of msgs pulled from the input queue /sec", "The current number of messages pulled from the input queue by the transport per second.", RateOfCountsPerSecond32
New-Object System.Diagnostics.CounterCreationData "# of msgs failures / sec", "The current number of failed processed messages by the transport per second.", RateOfCountsPerSecond32
New-Object System.Diagnostics.CounterCreationData "# of msgs successfully processed / sec", "The current number of messages processed successfully by the transport per second.", RateOfCountsPerSecond32
+ New-Object System.Diagnostics.CounterCreationData "# of msgs pulled from the input queue /sec", "The current number of messages pulled from the input queue by the transport per second.", RateOfCountsPerSecond32
+ New-Object System.Diagnostics.CounterCreationData "Retries", "A message has been scheduled for retry (FLR or SLR)", RateOfCountsPerSecond32
))
if ([System.Diagnostics.PerformanceCounterCategory]::Exists($category.Name)) {
+
foreach($counter in $counters){
$exists = [System.Diagnostics.PerformanceCounterCategory]::CounterExists($counter.CounterName, $category.Name)
if (!$exists){
@@ -28,11 +35,11 @@ Function InstallNSBPerfCounters {
if (![System.Diagnostics.PerformanceCounterCategory]::Exists($category.Name)) {
Write-Host "Creating the performance counter category"
[void] [System.Diagnostics.PerformanceCounterCategory]::Create($category.Name, $category.Description, [System.Diagnostics.PerformanceCounterCategoryType]::MultiInstance, $counters)
- }
+ }
else {
Write-Host "No performance counters have to be created"
}
[System.Diagnostics.PerformanceCounter]::CloseSharedResources()
}
-InstallNSBPerfCounters
\ No newline at end of file
+InstallNSBPerfCounters
diff --git a/src/ScriptBuilderTask.Tests/PowershellCodeGenerationTests.cs b/src/ScriptBuilderTask.Tests/PowershellCodeGenerationTests.cs
index c4832f1..aca44c6 100644
--- a/src/ScriptBuilderTask.Tests/PowershellCodeGenerationTests.cs
+++ b/src/ScriptBuilderTask.Tests/PowershellCodeGenerationTests.cs
@@ -35,6 +35,8 @@ public void SetUp()
[MethodImpl(MethodImplOptions.NoInlining)]
public void Generates()
{
+ GenericDiffReporter.RegisterTextFileTypes(".ps1");
+
task.Execute();
GenericDiffReporter.RegisterTextFileTypes(".ps1");
diff --git a/src/ScriptBuilderTask.Tests/ScriptBuilderTask.Tests.csproj b/src/ScriptBuilderTask.Tests/ScriptBuilderTask.Tests.csproj
index e03e465..508f07b 100644
--- a/src/ScriptBuilderTask.Tests/ScriptBuilderTask.Tests.csproj
+++ b/src/ScriptBuilderTask.Tests/ScriptBuilderTask.Tests.csproj
@@ -1,72 +1,32 @@
-
-
-
+
+
- Debug
- AnyCPU
- {8174164E-52B8-4878-BFB0-34C81A31930E}
- Library
- Properties
- ScriptBuilderTask.Tests
- ScriptBuilderTask.Tests
- v4.5.2
- 512
-
-
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
-
-
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
+ net452
+ true
+ $(SolutionDir)NServiceBus.snk
+
+
+
+
+
-
- ..\packages\ApprovalTests.3.0.13\lib\net40\ApprovalTests.dll
-
-
- ..\packages\ApprovalUtilities.3.0.13\lib\net45\ApprovalUtilities.dll
-
-
- ..\packages\ApprovalUtilities.3.0.13\lib\net45\ApprovalUtilities.Net45.dll
-
-
- ..\packages\NServiceBus.6.3.4\lib\net452\NServiceBus.Core.dll
-
-
- ..\packages\NServiceBus.Metrics.1.0.1\lib\net452\NServiceBus.Metrics.dll
-
-
- ..\packages\NUnit.3.6.1\lib\net45\nunit.framework.dll
-
-
-
-
+
-
-
-
-
+
-
-
+
+
+
+
+
+
-
- {08fd76cb-6988-485a-a535-b3129af89c60}
- ScriptBuilderTask
-
+
+
-
+
\ No newline at end of file
diff --git a/src/ScriptBuilderTask.Tests/packages.config b/src/ScriptBuilderTask.Tests/packages.config
deleted file mode 100644
index ed9da01..0000000
--- a/src/ScriptBuilderTask.Tests/packages.config
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/ScriptBuilderTask/AssemblyInfo.cs b/src/ScriptBuilderTask/AssemblyInfo.cs
deleted file mode 100644
index d422713..0000000
--- a/src/ScriptBuilderTask/AssemblyInfo.cs
+++ /dev/null
@@ -1,4 +0,0 @@
-using System.Reflection;
-
-[assembly: AssemblyTitle("NServiceBus.Metrics.PerformanceCounters.Task")]
-[assembly: AssemblyProduct("NServiceBus.Metrics.PerformanceCounters.Task")]
diff --git a/src/ScriptBuilder/BuildScriptVariant.cs b/src/ScriptBuilderTask/BuildScriptVariant.cs
similarity index 100%
rename from src/ScriptBuilder/BuildScriptVariant.cs
rename to src/ScriptBuilderTask/BuildScriptVariant.cs
diff --git a/src/ScriptBuilderTask/CSharpCounterWriter.cs b/src/ScriptBuilderTask/CSharpCounterWriter.cs
new file mode 100644
index 0000000..22d2459
--- /dev/null
+++ b/src/ScriptBuilderTask/CSharpCounterWriter.cs
@@ -0,0 +1,99 @@
+namespace NServiceBus.Metrics.PerformanceCounters
+{
+ using System.Collections.Generic;
+ using System.IO;
+ using System.Text;
+
+ static class CSharpCounterWriter
+ {
+ public static void WriteCode(string scriptPath, IEnumerable durations, IEnumerable signals, Dictionary legacyInstanceNameMap)
+ {
+ var outputPath = Path.Combine(scriptPath, "Counters.g.cs");
+ using (var streamWriter = File.CreateText(outputPath))
+ {
+ var stringBuilder = new StringBuilder();
+
+ var slaCounterDefinition = @"new CounterCreationData(""SLA violation countdown"", ""Seconds until the SLA for this endpoint is breached."", PerformanceCounterType.NumberOfItems32),";
+ stringBuilder.AppendLine(slaCounterDefinition.PadLeft(slaCounterDefinition.Length + 8));
+
+ foreach (var duration in durations)
+ {
+ var averageTimerName = duration.Name.GetAverageTimerCounterName();
+ var averageTimerBase = duration.Name.GetAverageTimerBaseCounterName();
+
+ var durationAverageDefinition = $@"new CounterCreationData(""{averageTimerName}"", ""{duration.Description}"", PerformanceCounterType.AverageTimer32),";
+ stringBuilder.AppendLine(durationAverageDefinition.PadLeft(durationAverageDefinition.Length + 8));
+
+ var durationBaseDefinition = $@"new CounterCreationData(""{averageTimerBase}"", ""{duration.Description}"", PerformanceCounterType.AverageBase),";
+ stringBuilder.AppendLine(durationBaseDefinition.PadLeft(durationBaseDefinition.Length + 8));
+
+ if (duration.Name == CounterNameConventions.ProcessingTime || duration.Name == CounterNameConventions.CriticalTime)
+ {
+ var legacyTimerDefinition = $@"new CounterCreationData(""{duration.Name}"", ""{duration.Description}"", PerformanceCounterType.NumberOfItems32),";
+ stringBuilder.AppendLine(legacyTimerDefinition.PadLeft(legacyTimerDefinition.Length + 8));
+ }
+ }
+
+ foreach (var signal in signals)
+ {
+ legacyInstanceNameMap.TryGetValue(signal.Name, out var instanceName);
+
+ var signalDefinition = $@"new CounterCreationData(""{instanceName ?? signal.Name}"", ""{signal.Description}"", PerformanceCounterType.RateOfCountsPerSecond32),";
+ stringBuilder.AppendLine(signalDefinition.PadLeft(signalDefinition.Length + 8));
+ }
+
+ streamWriter.Write(Template, stringBuilder);
+ }
+ }
+
+ const string Template = @"using System;
+using System.Diagnostics;
+using System.Security;
+using System.Runtime.CompilerServices;
+
+[CompilerGenerated]
+public static class CounterCreator
+{{
+ public static void Create()
+ {{
+ var counterCreationCollection = new CounterCreationDataCollection(Counters);
+ try
+ {{
+ var categoryName = ""NServiceBus"";
+
+ if (PerformanceCounterCategory.Exists(categoryName))
+ {{
+ foreach (CounterCreationData counter in counterCreationCollection)
+ {{
+ if (!PerformanceCounterCategory.CounterExists(counter.CounterName, categoryName))
+ {{
+ PerformanceCounterCategory.Delete(categoryName);
+ break;
+ }}
+ }}
+ }}
+
+ if (PerformanceCounterCategory.Exists(categoryName) == false)
+ {{
+ PerformanceCounterCategory.Create(
+ categoryName: categoryName,
+ categoryHelp: ""NServiceBus statistics"",
+ categoryType: PerformanceCounterCategoryType.MultiInstance,
+ counterData: counterCreationCollection);
+ }}
+
+ PerformanceCounter.CloseSharedResources();
+ }}
+ catch (Exception ex) when(ex is SecurityException || ex is UnauthorizedAccessException)
+ {{
+ throw new Exception(""Execution requires elevated permissions"", ex);
+ }}
+ }}
+
+ static CounterCreationData[] Counters = new CounterCreationData[]
+ {{
+{0}
+ }};
+}}";
+ }
+}
\ No newline at end of file
diff --git a/src/ScriptBuilder/CecilExtensions.cs b/src/ScriptBuilderTask/CecilExtensions.cs
similarity index 86%
rename from src/ScriptBuilder/CecilExtensions.cs
rename to src/ScriptBuilderTask/CecilExtensions.cs
index c9d8ab0..01eebd2 100644
--- a/src/ScriptBuilder/CecilExtensions.cs
+++ b/src/ScriptBuilderTask/CecilExtensions.cs
@@ -47,10 +47,20 @@ public static IEnumerable AllClasses(this ModuleDefinition modul
.Where(x => x.IsClass);
}
+
public static string GetFileName(this TypeDefinition type)
{
foreach (var method in type.Methods)
{
+ var debugInformation = method.DebugInformation;
+ if (debugInformation == null)
+ {
+ continue;
+ }
+ if (!debugInformation.HasSequencePoints != true)
+ {
+ continue;
+ }
var body = method.Body;
if (body?.Instructions == null)
{
@@ -58,7 +68,7 @@ public static string GetFileName(this TypeDefinition type)
}
foreach (var instruction in body.Instructions)
{
- var point = instruction.SequencePoint;
+ var point = debugInformation.GetSequencePoint(instruction);
if (point?.Document?.Url == null)
{
continue;
diff --git a/src/ScriptBuilderTask/CounterNameConventions.cs b/src/ScriptBuilderTask/CounterNameConventions.cs
new file mode 100644
index 0000000..9a4a687
--- /dev/null
+++ b/src/ScriptBuilderTask/CounterNameConventions.cs
@@ -0,0 +1,18 @@
+namespace NServiceBus.Metrics.PerformanceCounters
+{
+ static class CounterNameConventions
+ {
+ public static string GetAverageTimerCounterName(this string durationName)
+ {
+ return $"{durationName} Average";
+ }
+
+ public static string GetAverageTimerBaseCounterName(this string durationName)
+ {
+ return $"{durationName} AverageBase";
+ }
+
+ public const string ProcessingTime = "Processing Time";
+ public const string CriticalTime = "Critical Time";
+ }
+}
\ No newline at end of file
diff --git a/src/ScriptBuilder/CounterWriter.cs b/src/ScriptBuilderTask/CounterWriter.cs
similarity index 89%
rename from src/ScriptBuilder/CounterWriter.cs
rename to src/ScriptBuilderTask/CounterWriter.cs
index cadf1fb..d3bdab2 100644
--- a/src/ScriptBuilder/CounterWriter.cs
+++ b/src/ScriptBuilderTask/CounterWriter.cs
@@ -8,12 +8,12 @@ public static class CounterWriter
{
public static void WriteScript(string scriptPath, BuildScriptVariant variant, ModuleDefinition module, Action logError)
{
- var timers = AllTimersDefinitionReader.GetTimers(module, (exception, type) =>
+ var timers = AllDurationsDefinitionReader.GetDurations(module, (exception, type) =>
{
logError($"Error in '{type.FullName}'. Error:{exception.Message}", type.GetFileName());
});
- var meters = AllMetersDefinitionReader.GetMeters(module, (exception, type) =>
+ var meters = AllSignalsDefinitionReader.GetSignals(module, (exception, type) =>
{
logError($"Error in '{type.FullName}'. Error:{exception.Message}", type.GetFileName());
});
diff --git a/src/ScriptBuilder/Timers/AllTimersDefinitionReader.cs b/src/ScriptBuilderTask/Durations/AllDurationsDefinitionReader.cs
similarity index 60%
rename from src/ScriptBuilder/Timers/AllTimersDefinitionReader.cs
rename to src/ScriptBuilderTask/Durations/AllDurationsDefinitionReader.cs
index 803c88e..6220f5a 100644
--- a/src/ScriptBuilder/Timers/AllTimersDefinitionReader.cs
+++ b/src/ScriptBuilderTask/Durations/AllDurationsDefinitionReader.cs
@@ -4,17 +4,16 @@
using System.Collections.Generic;
using Mono.Cecil;
- static class AllTimersDefinitionReader
+ static class AllDurationsDefinitionReader
{
- public static IEnumerable GetTimers(ModuleDefinition module, Action logError)
+ public static IEnumerable GetDurations(ModuleDefinition module, Action logError)
{
- var timerDefinitions = new List();
+ var timerDefinitions = new List();
foreach (var type in module.AllClasses())
{
try
{
- List definition;
- if (TimerDefinitionReader.TryGetTimerDefinition(type, out definition))
+ if (DurationDefinitionReader.TryGetDurationDefinition(type, out var definition))
{
timerDefinitions.AddRange(definition);
}
diff --git a/src/ScriptBuilder/Timers/TimerDefinition.cs b/src/ScriptBuilderTask/Durations/DurationDefinition.cs
similarity index 70%
rename from src/ScriptBuilder/Timers/TimerDefinition.cs
rename to src/ScriptBuilderTask/Durations/DurationDefinition.cs
index 719f7ff..86ee1df 100644
--- a/src/ScriptBuilder/Timers/TimerDefinition.cs
+++ b/src/ScriptBuilderTask/Durations/DurationDefinition.cs
@@ -1,8 +1,8 @@
namespace NServiceBus.Metrics.PerformanceCounters
{
- class TimerDefinition
+ class DurationDefinition
{
- public TimerDefinition(string name, string description)
+ public DurationDefinition(string name, string description)
{
Name = name;
Description = description;
diff --git a/src/ScriptBuilder/Meters/MeterDefinitionReader.cs b/src/ScriptBuilderTask/Durations/DurationDefinitionReader.cs
similarity index 52%
rename from src/ScriptBuilder/Meters/MeterDefinitionReader.cs
rename to src/ScriptBuilderTask/Durations/DurationDefinitionReader.cs
index 2f1bc56..5a38e35 100644
--- a/src/ScriptBuilder/Meters/MeterDefinitionReader.cs
+++ b/src/ScriptBuilderTask/Durations/DurationDefinitionReader.cs
@@ -4,22 +4,21 @@
using System.Linq;
using Mono.Cecil;
- static class MeterDefinitionReader
+ static class DurationDefinitionReader
{
- public static bool TryGetMeterDefinition(TypeDefinition type, out List definitions)
+ public static bool TryGetDurationDefinition(TypeDefinition type, out List definitions)
{
- definitions = new List();
- if (type.BaseType != null && type.BaseType.FullName == "NServiceBus.Metrics.MetricBuilder")
+ definitions = new List();
+ if (type.BaseType != null && type.BaseType.FullName == "DurationProbeBuilder")
{
- var attributes = type.Fields
- .Select(f => f.GetSingleAttribute("NServiceBus.Metrics.MeterAttribute"))
- .Where(c => c != null);
+ var attributes = type.CustomAttributes.Where(a => a.AttributeType.FullName == "ProbePropertiesAttribute");
foreach (var attribute in attributes)
{
var name = attribute.ParameterValue("name");
var description = attribute.ParameterValue("description");
- definitions.Add(new MeterDefinition(name, description));
+
+ definitions.Add(new DurationDefinition(name, description));
}
}
return definitions.Count > 0;
diff --git a/src/ScriptBuilder/ErrorsException.cs b/src/ScriptBuilderTask/ErrorsException.cs
similarity index 100%
rename from src/ScriptBuilder/ErrorsException.cs
rename to src/ScriptBuilderTask/ErrorsException.cs
diff --git a/src/ScriptBuilderTask/ExceptionExtensions.cs b/src/ScriptBuilderTask/ExceptionExtensions.cs
index eeb3417..de0bcf6 100644
--- a/src/ScriptBuilderTask/ExceptionExtensions.cs
+++ b/src/ScriptBuilderTask/ExceptionExtensions.cs
@@ -40,14 +40,6 @@ public static string ToFriendlyString(this Exception exception)
stringBuilder.Append(Environment.NewLine);
}
- if (exception.TargetSite != null)
- {
- stringBuilder.Append("TargetSite:");
- stringBuilder.Append(Environment.NewLine);
- stringBuilder.Append(exception.TargetSite);
- stringBuilder.Append(Environment.NewLine);
- }
-
exception = exception.InnerException;
}
diff --git a/src/ScriptBuilderTask/InnerTask.cs b/src/ScriptBuilderTask/InnerTask.cs
index e64ce15..62e83aa 100644
--- a/src/ScriptBuilderTask/InnerTask.cs
+++ b/src/ScriptBuilderTask/InnerTask.cs
@@ -37,8 +37,7 @@ public void Execute()
void PromoteFiles(ModuleDefinition moduleDefinition, string scriptPath)
{
- string customPath;
- if (!ScriptPromotionPathReader.TryRead(moduleDefinition, out customPath))
+ if (!ScriptPromotionPathReader.TryRead(moduleDefinition, out var customPath))
{
return;
}
diff --git a/packaging/nuget/NServiceBus.Metrics.PerformanceCounters.MsBuild.nuspec b/src/ScriptBuilderTask/NServiceBus.Metrics.PerformanceCounters.MsBuild.nuspec
similarity index 60%
rename from packaging/nuget/NServiceBus.Metrics.PerformanceCounters.MsBuild.nuspec
rename to src/ScriptBuilderTask/NServiceBus.Metrics.PerformanceCounters.MsBuild.nuspec
index 6277bb2..b7fd5ae 100644
--- a/packaging/nuget/NServiceBus.Metrics.PerformanceCounters.MsBuild.nuspec
+++ b/src/ScriptBuilderTask/NServiceBus.Metrics.PerformanceCounters.MsBuild.nuspec
@@ -1,9 +1,8 @@
- NServiceBus.Metrics.PerformanceCounters.MsBuild
+ $id$
$version$
- NServiceBus.Metrics.PerformanceCounters.MsBuild
$authors$
$owners$
true
@@ -11,7 +10,7 @@
$projectUrl$
$requireLicenseAcceptance$
$iconUrl$
- MsBuild Task for building deployment scripts for the NServiceBus.Metrics.PerformanceCounters package.
+ $description$
$copyright$
$tags$
@@ -19,7 +18,8 @@
-
-
+
+
+
diff --git a/packaging/nuget/NServiceBus.Metrics.PerformanceCounters.MsBuild.targets b/src/ScriptBuilderTask/NServiceBus.Metrics.PerformanceCounters.MsBuild.targets
similarity index 63%
rename from packaging/nuget/NServiceBus.Metrics.PerformanceCounters.MsBuild.targets
rename to src/ScriptBuilderTask/NServiceBus.Metrics.PerformanceCounters.MsBuild.targets
index 9afa68e..8bf8673 100644
--- a/packaging/nuget/NServiceBus.Metrics.PerformanceCounters.MsBuild.targets
+++ b/src/ScriptBuilderTask/NServiceBus.Metrics.PerformanceCounters.MsBuild.targets
@@ -1,16 +1,29 @@
-
- $(ProjectDir)$(IntermediateOutputPath)NServiceBus.Metrics.PerformanceCounters\
-
+
+
+
+ $(MSBuildThisFileDirectory)..\netstandard\NServiceBus.Metrics.PerformanceCounters.Task.dll
+
+
+
+
+ $(MSBuildThisFileDirectory)..\netclassic\NServiceBus.Metrics.PerformanceCounters.Task.dll
+
+
+
+ AssemblyFile="$(ScriptBuilderTaskPath)" />
+ Name="PerformanceCountersScriptBuilder"
+ Condition="'$(DesignTimeBuild)' != 'true'">
+
+ $(ProjectDir)$(IntermediateOutputPath)NServiceBus.Metrics.PerformanceCounters\
+
-
+
+ Name="AddScriptsToGetCopyToOutputDirectoryItems"
+ Condition="'$(DesignTimeBuild)' != 'true'">
diff --git a/src/ScriptBuilderTask/PowerShellCounterWriter.cs b/src/ScriptBuilderTask/PowerShellCounterWriter.cs
new file mode 100644
index 0000000..461e338
--- /dev/null
+++ b/src/ScriptBuilderTask/PowerShellCounterWriter.cs
@@ -0,0 +1,85 @@
+namespace NServiceBus.Metrics.PerformanceCounters
+{
+ using System.Collections.Generic;
+ using System.IO;
+ using System.Text;
+
+ static class PowerShellCounterWriter
+ {
+ public static void WriteScript(string scriptPath, IEnumerable durations, IEnumerable signals, Dictionary legacyInstanceNameMap)
+ {
+ var outputPath = Path.Combine(scriptPath, "CreateNSBPerfCounters.ps1");
+ using (var streamWriter = File.CreateText(outputPath))
+ {
+ var stringBuilder = new StringBuilder();
+
+ var slaCounterDefinition = @"New-Object System.Diagnostics.CounterCreationData ""SLA violation countdown"", ""Seconds until the SLA for this endpoint is breached."", NumberOfItems32";
+ stringBuilder.AppendLine(slaCounterDefinition.PadLeft(slaCounterDefinition.Length + 8));
+
+ foreach (var duration in durations)
+ {
+ var averageTimerName = duration.Name.GetAverageTimerCounterName();
+ var averageTimerBase = duration.Name.GetAverageTimerBaseCounterName();
+
+ var durationAverageDefinition = $@"New-Object System.Diagnostics.CounterCreationData ""{averageTimerName}"", ""{duration.Description}"", AverageTimer32";
+ stringBuilder.AppendLine(durationAverageDefinition.PadLeft(durationAverageDefinition.Length + 8));
+
+ var durationBaseDefinition = $@"New-Object System.Diagnostics.CounterCreationData ""{averageTimerBase}"", ""{duration.Description}"", AverageBase";
+ stringBuilder.AppendLine(durationBaseDefinition.PadLeft(durationBaseDefinition.Length + 8));
+
+ if (duration.Name == CounterNameConventions.ProcessingTime || duration.Name == CounterNameConventions.CriticalTime)
+ {
+ var legacyTimerDefinition = $@"New-Object System.Diagnostics.CounterCreationData ""{duration.Name}"", ""{duration.Description}"", NumberOfItems32";
+ stringBuilder.AppendLine(legacyTimerDefinition.PadLeft(legacyTimerDefinition.Length + 8));
+ }
+ }
+
+ foreach (var signal in signals)
+ {
+ legacyInstanceNameMap.TryGetValue(signal.Name, out var instanceName);
+
+ var signalDefinition = $@"New-Object System.Diagnostics.CounterCreationData ""{instanceName ?? signal.Name}"", ""{signal.Description}"", RateOfCountsPerSecond32";
+ stringBuilder.AppendLine(signalDefinition.PadLeft(signalDefinition.Length + 8));
+ }
+
+ streamWriter.Write(Template, stringBuilder);
+ }
+ }
+
+ const string Template = @"
+#requires -RunAsAdministrator
+Function InstallNSBPerfCounters {{
+
+ $category = @{{Name=""NServiceBus""; Description=""NServiceBus statistics""}}
+ $counters = New-Object System.Diagnostics.CounterCreationDataCollection
+ $counters.AddRange(@(
+{0}
+ ))
+
+ if ([System.Diagnostics.PerformanceCounterCategory]::Exists($category.Name)) {{
+
+ foreach($counter in $counters){{
+ $exists = [System.Diagnostics.PerformanceCounterCategory]::CounterExists($counter.CounterName, $category.Name)
+ if (!$exists){{
+ Write-Host ""One or more counters are missing.The performance counter category will be recreated""
+ [System.Diagnostics.PerformanceCounterCategory]::Delete($category.Name)
+
+ break
+ }}
+ }}
+ }}
+
+ if (![System.Diagnostics.PerformanceCounterCategory]::Exists($category.Name)) {{
+ Write-Host ""Creating the performance counter category""
+ [void] [System.Diagnostics.PerformanceCounterCategory]::Create($category.Name, $category.Description, [System.Diagnostics.PerformanceCounterCategoryType]::MultiInstance, $counters)
+ }}
+ else {{
+ Write-Host ""No performance counters have to be created""
+ }}
+
+ [System.Diagnostics.PerformanceCounter]::CloseSharedResources()
+}}
+InstallNSBPerfCounters
+";
+ }
+}
\ No newline at end of file
diff --git a/src/ScriptBuilderTask/ScriptBuilderTask.cs b/src/ScriptBuilderTask/ScriptBuilderTask.cs
index 1bf2863..215a37c 100644
--- a/src/ScriptBuilderTask/ScriptBuilderTask.cs
+++ b/src/ScriptBuilderTask/ScriptBuilderTask.cs
@@ -5,6 +5,7 @@
using System.Diagnostics;
using System.IO;
using System.Linq;
+ using System.Reflection;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
@@ -28,17 +29,17 @@ public class ScriptBuilderTask : Task
[Required]
public string SolutionDirectory { get; set; }
- public Dictionary ReferenceDictionary { get; } = new Dictionary(StringComparer.InvariantCultureIgnoreCase);
+ public Dictionary ReferenceDictionary { get; } = new Dictionary(StringComparer.OrdinalIgnoreCase);
public override bool Execute()
{
logger = new BuildLogger(BuildEngine);
- logger.LogInfo($"ScriptBuilderTask (version {typeof(ScriptBuilderTask).Assembly.GetName().Version}) Executing");
+ logger.LogInfo($"ScriptBuilderTask (version {typeof(ScriptBuilderTask).GetTypeInfo().Assembly.GetName().Version}) Executing");
var stopwatch = Stopwatch.StartNew();
var referenceCopyLocalPaths = ReferenceCopyLocalPaths.Select(x => x.ItemSpec);
- var splitReferences = References.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries).Union(referenceCopyLocalPaths, StringComparer.InvariantCultureIgnoreCase);
+ var splitReferences = References.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries).Union(referenceCopyLocalPaths, StringComparer.OrdinalIgnoreCase);
foreach (var filePath in splitReferences)
{
var fileNameWithExtension = Path.GetFileName(filePath);
@@ -92,8 +93,7 @@ void ValidateInputs()
throw new ErrorsException($"SolutionDirectory '{SolutionDirectory}' does not exist.");
}
- string filePath;
- if (!ReferenceDictionary.TryGetValue("NServiceBus.Metrics.dll", out filePath))
+ if (!ReferenceDictionary.TryGetValue("NServiceBus.Metrics.dll", out _))
{
throw new ErrorsException("NServiceBus.Metrics.dll is not referenced in this assembly.");
}
diff --git a/src/ScriptBuilderTask/ScriptBuilderTask.csproj b/src/ScriptBuilderTask/ScriptBuilderTask.csproj
index e8bee3e..6f792a2 100644
--- a/src/ScriptBuilderTask/ScriptBuilderTask.csproj
+++ b/src/ScriptBuilderTask/ScriptBuilderTask.csproj
@@ -1,103 +1,65 @@
-
-
-
+
+
- Debug
- AnyCPU
- {08FD76CB-6988-485A-A535-B3129AF89C60}
- Library
- Properties
- NServiceBus.Metrics.PerformanceCounters
- NServiceBus.Metrics.PerformanceCounters.Task
- v4.5.2
- 512
- NServiceBus.Metrics.PerformanceCounters.MsBuild
+ net452;netstandard1.5
true
+ NServiceBus.Metrics.PerformanceCounters.Task
$(SolutionDir)NServiceBus.snk
+ ..\..\binaries\
+ $(NoWarn);CS1591
-
- true
- full
- false
- bin\Debug
- DEBUG;TRACE
- prompt
- 4
-
-
- pdbonly
- true
- bin\Release
- TRACE
- prompt
- 4
-
+
+
+
+
+
+
+
+
-
- ..\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.dll
-
-
- ..\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.Mdb.dll
-
-
- ..\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.Pdb.dll
-
-
- ..\packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.Rocks.dll
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {1BDA0A75-91F6-4412-A780-7BE9322B2A4E}
- ScriptBuilder
- True
-
-
-
-
- Designer
-
+
+
+
+
+
+
-
-
-
+
+
+ NServiceBus.Metrics.PerformanceCounters.MsBuild
+ MsBuild Task for building deployment scripts for the NServiceBus.Metrics.PerformanceCounters package.
+ $(MSBuildThisFileDirectory)$(PackageId).nuspec
+ true
+
+
+
- This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+ id=$(PackageId);version=$(PackageVersion);authors=$(Authors);owners=$(Authors);licenseUrl=$(PackageLicenseUrl);requireLicenseAcceptance=$(PackageRequireLicenseAcceptance);iconUrl=$(PackageIconUrl);projectUrl=$(PackageProjectUrl);description=$(Description);copyright=$(Copyright);tags=$(PackageTags)
-
-
-
-
+
+
+
+ true
+
+
+
- "$(SolutionDir)..\Tools\ilmerge.exe"
- $(ProjectDir)bin\$(ConfigurationName)\NServiceBus.Metrics.PerformanceCounters.Builder.dll
- $(ProjectDir)bin\$(ConfigurationName)\NServiceBus.Metrics.PerformanceCounters.Task.dll
- $(ProjectDir)bin\$(ConfigurationName)\Mono.Cecil.dll
- $(SolutionDir)..\binaries\NServiceBus.Metrics.PerformanceCounters.Task.dll
- $(SolutionDir)..\binaries\NServiceBus.Metrics.PerformanceCounters.Task.pdb
- $(SolutionDir)..\packaging\nuget\NServiceBus.Metrics.PerformanceCounters.MsBuild.targets
+ $(ProjectDir)$(OutputPath)temp
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/ScriptBuilder/ScriptPromotionPathReader.cs b/src/ScriptBuilderTask/ScriptPromotionPathReader.cs
similarity index 100%
rename from src/ScriptBuilder/ScriptPromotionPathReader.cs
rename to src/ScriptBuilderTask/ScriptPromotionPathReader.cs
diff --git a/src/ScriptBuilder/ScriptVariantReader.cs b/src/ScriptBuilderTask/ScriptVariantReader.cs
similarity index 100%
rename from src/ScriptBuilder/ScriptVariantReader.cs
rename to src/ScriptBuilderTask/ScriptVariantReader.cs
diff --git a/src/ScriptBuilder/Meters/AllMetersDefinitionReader.cs b/src/ScriptBuilderTask/Signals/AllSignalsDefinitionReader.cs
similarity index 60%
rename from src/ScriptBuilder/Meters/AllMetersDefinitionReader.cs
rename to src/ScriptBuilderTask/Signals/AllSignalsDefinitionReader.cs
index 1dbecef..6b1be48 100644
--- a/src/ScriptBuilder/Meters/AllMetersDefinitionReader.cs
+++ b/src/ScriptBuilderTask/Signals/AllSignalsDefinitionReader.cs
@@ -4,17 +4,16 @@
using System.Collections.Generic;
using Mono.Cecil;
- static class AllMetersDefinitionReader
+ static class AllSignalsDefinitionReader
{
- public static IEnumerable GetMeters(ModuleDefinition module, Action logError)
+ public static IEnumerable GetSignals(ModuleDefinition module, Action logError)
{
- var timerDefinitions = new List();
+ var timerDefinitions = new List();
foreach (var type in module.AllClasses())
{
try
{
- List definition;
- if (MeterDefinitionReader.TryGetMeterDefinition(type, out definition))
+ if (SignalDefinitionReader.TryGetSignalDefinition(type, out var definition))
{
timerDefinitions.AddRange(definition);
}
diff --git a/src/ScriptBuilder/Meters/MeterDefinition.cs b/src/ScriptBuilderTask/Signals/SignalDefinition.cs
similarity index 71%
rename from src/ScriptBuilder/Meters/MeterDefinition.cs
rename to src/ScriptBuilderTask/Signals/SignalDefinition.cs
index eb6369e..4a8ee3c 100644
--- a/src/ScriptBuilder/Meters/MeterDefinition.cs
+++ b/src/ScriptBuilderTask/Signals/SignalDefinition.cs
@@ -1,8 +1,8 @@
namespace NServiceBus.Metrics.PerformanceCounters
{
- class MeterDefinition
+ class SignalDefinition
{
- public MeterDefinition(string name, string description)
+ public SignalDefinition(string name, string description)
{
Name = name;
Description = description;
diff --git a/src/ScriptBuilderTask/Signals/SignalDefinitionReader.cs b/src/ScriptBuilderTask/Signals/SignalDefinitionReader.cs
new file mode 100644
index 0000000..76e7693
--- /dev/null
+++ b/src/ScriptBuilderTask/Signals/SignalDefinitionReader.cs
@@ -0,0 +1,26 @@
+namespace NServiceBus.Metrics.PerformanceCounters
+{
+ using System.Collections.Generic;
+ using System.Linq;
+ using Mono.Cecil;
+
+ static class SignalDefinitionReader
+ {
+ public static bool TryGetSignalDefinition(TypeDefinition type, out List definitions)
+ {
+ definitions = new List();
+ if (type.BaseType != null && type.BaseType.FullName == "SignalProbeBuilder")
+ {
+ var attributes = type.CustomAttributes.Where(a => a.AttributeType.FullName == "ProbePropertiesAttribute");
+
+ foreach (var attribute in attributes)
+ {
+ var name = attribute.ParameterValue("name");
+ var description = attribute.ParameterValue("description");
+ definitions.Add(new SignalDefinition(name, description));
+ }
+ }
+ return definitions.Count > 0;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ScriptBuilderTask/packages.config b/src/ScriptBuilderTask/packages.config
deleted file mode 100644
index d6cd986..0000000
--- a/src/ScriptBuilderTask/packages.config
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/nuget.config b/src/nuget.config
index 9f16f77..b6d57e1 100644
--- a/src/nuget.config
+++ b/src/nuget.config
@@ -9,7 +9,6 @@
-
diff --git a/tools/ILMerge.exe b/tools/ILMerge.exe
deleted file mode 100644
index e401808..0000000
Binary files a/tools/ILMerge.exe and /dev/null differ