From 83fb42a387709c5c1633aafe14ea1548eb668480 Mon Sep 17 00:00:00 2001 From: Michael Tsibelman Date: Wed, 30 Aug 2017 16:59:55 +0300 Subject: [PATCH 1/9] Use one health check for all objects. (#77) One health check for all config objects --- Gigya.Microdot.Configuration/ConfigCache.cs | 6 +-- Gigya.Microdot.Configuration/ConfigItem.cs | 2 +- .../EnvironmentVariableProvider.cs | 7 ---- .../Gigya.Microdot.Configuration.csproj | 1 - .../Objects/ConfigObjectCreator.cs | 8 ++-- .../IEnvironmentVariableProvider.cs | 3 ++ Gigya.Microdot.Ninject/MicrodotModule.cs | 3 ++ .../Gigya.Microdot.SharedLogic.csproj | 1 + .../Monitor/AggregatingHealthStatus.cs | 41 ++++++++++--------- .../Monitor/HealthMonitor.cs | 4 +- paket.dependencies | 13 +++--- paket.lock | 8 ++-- .../Configuration/TypedConfigTest.cs | 2 +- 13 files changed, 53 insertions(+), 46 deletions(-) rename Gigya.Microdot.Configuration/ConfigurationHealthCheck.cs => Gigya.Microdot.SharedLogic/Monitor/AggregatingHealthStatus.cs (52%) diff --git a/Gigya.Microdot.Configuration/ConfigCache.cs b/Gigya.Microdot.Configuration/ConfigCache.cs index 5523e928..8561f73b 100644 --- a/Gigya.Microdot.Configuration/ConfigCache.cs +++ b/Gigya.Microdot.Configuration/ConfigCache.cs @@ -45,13 +45,13 @@ public ConfigCache(IConfigItemsSource source, IConfigurationDataWatcher watcher, Log = log; ConfigChangedBroadcastBlock = new BroadcastBlock(null); - watcher.DataChanges.LinkTo(new ActionBlock(nothing => Refresh(nothing))); + watcher.DataChanges.LinkTo(new ActionBlock(nothing => Refresh())); - Refresh(true, false).GetAwaiter().GetResult(); + Refresh(false).GetAwaiter().GetResult(); } - private async Task Refresh(bool nothing, bool catchExceptions=true) + private async Task Refresh(bool catchExceptions=true) { //Prevents faulting of action block try diff --git a/Gigya.Microdot.Configuration/ConfigItem.cs b/Gigya.Microdot.Configuration/ConfigItem.cs index a3ab1472..b2c69873 100644 --- a/Gigya.Microdot.Configuration/ConfigItem.cs +++ b/Gigya.Microdot.Configuration/ConfigItem.cs @@ -57,7 +57,7 @@ public List Overrides _overrides = new List(); return _overrides; } - set { _overrides = value; } + set => _overrides = value; } public string Value diff --git a/Gigya.Microdot.Configuration/EnvironmentVariableProvider.cs b/Gigya.Microdot.Configuration/EnvironmentVariableProvider.cs index f44bfc92..c482cd88 100644 --- a/Gigya.Microdot.Configuration/EnvironmentVariableProvider.cs +++ b/Gigya.Microdot.Configuration/EnvironmentVariableProvider.cs @@ -43,17 +43,10 @@ public EnvironmentVariableProvider(IEnvironment environment, EnvironmentVariable throw new EnvironmentException("One or more of the following environment variables, which are required, have not been set: %DC%, %ENV%"); } - /// Initialized with environment variable CONSUL public string ConsulAddress { get; } - /// - /// Initialized with environment variable DC - /// public string DataCenter { get; } - /// - /// Initialized with environment variable ENV - /// public string DeploymentEnvironment { get; } public string GetEnvironmentVariable(string name) { return _environment.GetEnvironmentVariable(name); } diff --git a/Gigya.Microdot.Configuration/Gigya.Microdot.Configuration.csproj b/Gigya.Microdot.Configuration/Gigya.Microdot.Configuration.csproj index c403c80a..26e81009 100644 --- a/Gigya.Microdot.Configuration/Gigya.Microdot.Configuration.csproj +++ b/Gigya.Microdot.Configuration/Gigya.Microdot.Configuration.csproj @@ -52,7 +52,6 @@ - diff --git a/Gigya.Microdot.Configuration/Objects/ConfigObjectCreator.cs b/Gigya.Microdot.Configuration/Objects/ConfigObjectCreator.cs index f485206a..10ad213a 100644 --- a/Gigya.Microdot.Configuration/Objects/ConfigObjectCreator.cs +++ b/Gigya.Microdot.Configuration/Objects/ConfigObjectCreator.cs @@ -58,7 +58,9 @@ public class ConfigObjectCreator private JObject Empty { get; } = new JObject(); private DataAnnotationsValidator.DataAnnotationsValidator Validator { get; } - public ConfigObjectCreator(Type objectType, ConfigCache configCache, UsageTracking usageTracking, ILog log, IHealthMonitor healthMonitor) + private readonly AggregatingHealthStatus healthStatus; + + public ConfigObjectCreator(Type objectType, ConfigCache configCache, UsageTracking usageTracking, ILog log, Func getAggregatedHealthCheck) { UsageTracking = usageTracking; Log = log; @@ -70,8 +72,8 @@ public ConfigObjectCreator(Type objectType, ConfigCache configCache, UsageTracki Create(); ConfigCache.ConfigChanged.LinkTo(new ActionBlock(c => Create())); InitializeBroadcast(); - - healthMonitor.SetHealthFunction($"{ObjectType.Name} Configuration", HealthCheck); + healthStatus = getAggregatedHealthCheck("Configuration"); + healthStatus.RegisterCheck(ObjectType.Name, HealthCheck); } diff --git a/Gigya.Microdot.Interfaces/Configuration/IEnvironmentVariableProvider.cs b/Gigya.Microdot.Interfaces/Configuration/IEnvironmentVariableProvider.cs index 1f3152b2..8c1c0fbc 100644 --- a/Gigya.Microdot.Interfaces/Configuration/IEnvironmentVariableProvider.cs +++ b/Gigya.Microdot.Interfaces/Configuration/IEnvironmentVariableProvider.cs @@ -33,6 +33,9 @@ public interface IEnvironmentVariableProvider /// string DeploymentEnvironment { get; } + /// + /// Initialized with environment variable CONSUL + /// string ConsulAddress { get; } string GetEnvironmentVariable(string name); diff --git a/Gigya.Microdot.Ninject/MicrodotModule.cs b/Gigya.Microdot.Ninject/MicrodotModule.cs index b8d77265..7d9a2e7b 100644 --- a/Gigya.Microdot.Ninject/MicrodotModule.cs +++ b/Gigya.Microdot.Ninject/MicrodotModule.cs @@ -26,6 +26,7 @@ using Gigya.Microdot.ServiceDiscovery.HostManagement; using Gigya.Microdot.ServiceProxy; using Gigya.Microdot.SharedLogic; +using Gigya.Microdot.SharedLogic.Monitor; using Metrics; using Ninject; using Ninject.Activation; @@ -34,6 +35,7 @@ namespace Gigya.Microdot.Ninject { + /// /// /// Contains all binding except hosting layer /// @@ -58,6 +60,7 @@ public override void Load() Kernel.BindPerKey(); Kernel.BindPerString(); + Kernel.BindPerString(); Rebind() .ToMethod(c => Metric.Context(GetTypeOfTarget(c).Name)) diff --git a/Gigya.Microdot.SharedLogic/Gigya.Microdot.SharedLogic.csproj b/Gigya.Microdot.SharedLogic/Gigya.Microdot.SharedLogic.csproj index 3e4f3c5f..1a5ab1e0 100644 --- a/Gigya.Microdot.SharedLogic/Gigya.Microdot.SharedLogic.csproj +++ b/Gigya.Microdot.SharedLogic/Gigya.Microdot.SharedLogic.csproj @@ -47,6 +47,7 @@ + diff --git a/Gigya.Microdot.Configuration/ConfigurationHealthCheck.cs b/Gigya.Microdot.SharedLogic/Monitor/AggregatingHealthStatus.cs similarity index 52% rename from Gigya.Microdot.Configuration/ConfigurationHealthCheck.cs rename to Gigya.Microdot.SharedLogic/Monitor/AggregatingHealthStatus.cs index 0737ea59..2346c503 100644 --- a/Gigya.Microdot.Configuration/ConfigurationHealthCheck.cs +++ b/Gigya.Microdot.SharedLogic/Monitor/AggregatingHealthStatus.cs @@ -21,37 +21,40 @@ #endregion using System; +using System.Collections.Concurrent; +using System.Linq; using Metrics; -using Metrics.Core; -namespace Gigya.Microdot.Configuration +namespace Gigya.Microdot.SharedLogic.Monitor { - public class ConfigurationHealthCheck : HealthCheck + public class AggregatingHealthStatus { - private bool _isHealthy; - private Exception _lastError; + private readonly ConcurrentDictionary> _checks = new ConcurrentDictionary>(); - public ConfigurationHealthCheck() - :base("Configuration") + public AggregatingHealthStatus(string componentName, IHealthMonitor healthMonitor) { - HealthChecks.RegisterHealthCheck(this); + healthMonitor.SetHealthFunction(componentName, HealthCheck); } - public void Healthy() + private HealthCheckResult HealthCheck() { - _isHealthy = true; - } - public void Unhealthy(Exception ex) - { - _lastError = ex; - _isHealthy = false; + var results =_checks + .Select(c => new {c.Key, Result = c.Value()}) + .OrderBy(c => c.Result.IsHealthy) + .ThenBy(c => c.Key) + .ToArray(); + + bool healthy = results.All(r => r.Result.IsHealthy); + string message = string.Join("\r\n", results.Select(r => r.Result.Message)); + + return healthy ? HealthCheckResult.Healthy(message) : HealthCheckResult.Unhealthy(message); } - protected override HealthCheckResult Check() + + public void RegisterCheck(string name, Func checkFunc) { - return _isHealthy - ? HealthCheckResult.Healthy() - : HealthCheckResult.Unhealthy(_lastError); + _checks.AddOrUpdate(name, checkFunc, (a, b) => checkFunc); } + } } \ No newline at end of file diff --git a/Gigya.Microdot.SharedLogic/Monitor/HealthMonitor.cs b/Gigya.Microdot.SharedLogic/Monitor/HealthMonitor.cs index c78b2c0a..f208146a 100644 --- a/Gigya.Microdot.SharedLogic/Monitor/HealthMonitor.cs +++ b/Gigya.Microdot.SharedLogic/Monitor/HealthMonitor.cs @@ -31,7 +31,9 @@ public sealed class HealthMonitor : IDisposable, IHealthMonitor { private static readonly ConcurrentDictionary _componentMonitors = new ConcurrentDictionary(); - public ComponentHealthMonitor SetHealthFunction(string component, Func check, Func> healthData=null) + public ComponentHealthMonitor SetHealthFunction(string component, + Func check, + Func> healthData=null) { var componentHealthMonitor = _componentMonitors.GetOrAdd(component, _ => new ComponentHealthMonitor(component, check)); componentHealthMonitor.Activate(); diff --git a/paket.dependencies b/paket.dependencies index da7bfb75..5889b9a0 100644 --- a/paket.dependencies +++ b/paket.dependencies @@ -33,13 +33,14 @@ nuget Microsoft.Extensions.DependencyInjection 1.1.1 nuget Ninject ~> 3.2 >= 3.2.1 nuget Ninject.Extensions.Factory ~> 3.2 >= 3.2.1 nuget Ninject.Extensions.Conventions ~> 3.2 >= 3.2.0 -nuget Castle.Core ~> 3.3 >= 3.3.0.0 +nuget Castle.Core ~> 3.3 #Tests only dependencies nuget NUnit ~> 3.0 -nuget RichardSzalay.MockHttp ~> 1.0 -nuget NSubstitute ~> 2.0 -nuget FluentAssertions ~> 4.0 -nuget Nuget.CommandLine ~> 4.0 -nuget Shouldly ~> 2.0 +nuget RichardSzalay.MockHttp +nuget NSubstitute +nuget FluentAssertions +nuget Nuget.CommandLine +nuget Shouldly + nuget NLog ~> 4.0 \ No newline at end of file diff --git a/paket.lock b/paket.lock index 5ebed90f..22ea305b 100644 --- a/paket.lock +++ b/paket.lock @@ -6,7 +6,7 @@ NUGET remote: https://www.nuget.org/api/v2 Castle.Core (3.3.3) DataAnnotationsValidator (2.0) - FluentAssertions (4.19.3) + FluentAssertions (4.19.4) Metrics.NET (0.5.3) Microsoft.Bcl (1.1.10) Microsoft.Bcl.Build (>= 1.0.14) @@ -68,9 +68,9 @@ NUGET Microsoft.Bcl.Build (>= 1.0.21) NLog (4.4.12) NSubstitute (2.0.3) - NuGet.CommandLine (4.1) - NUnit (3.7.1) - RichardSzalay.MockHttp (1.5) + NuGet.CommandLine (4.3) + NUnit (3.8.1) + RichardSzalay.MockHttp (3.1) System.Net.Http (>= 4.0) Shouldly (2.8.3) System.Collections.Immutable (1.4) diff --git a/tests/Gigya.Microdot.UnitTests/Configuration/TypedConfigTest.cs b/tests/Gigya.Microdot.UnitTests/Configuration/TypedConfigTest.cs index 6f5a7ba7..eb099d5c 100644 --- a/tests/Gigya.Microdot.UnitTests/Configuration/TypedConfigTest.cs +++ b/tests/Gigya.Microdot.UnitTests/Configuration/TypedConfigTest.cs @@ -264,7 +264,7 @@ public async Task ChangeToBrokenConfiguration() busSettings = extractor(); busSettings.RequestTimeoutInMs.ShouldBe(30000); - const string healthComponentName = "BusSettings Configuration"; + const string healthComponentName = "Configuration"; var healthMonitor = (FakeHealthMonitor) infraKernel.Get(); healthMonitor.Monitors.ShouldContainKey(healthComponentName); healthMonitor.Monitors[healthComponentName]().IsHealthy.ShouldBe(false); From d1a1c9f81d35c18db2019ce8ae29c037d77ea52b Mon Sep 17 00:00:00 2001 From: Michael Tsibelman Date: Wed, 30 Aug 2017 17:09:01 +0300 Subject: [PATCH 2/9] Update SolutionVersion.cs --- SolutionVersion.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/SolutionVersion.cs b/SolutionVersion.cs index 9f87da75..cdfc734e 100644 --- a/SolutionVersion.cs +++ b/SolutionVersion.cs @@ -28,9 +28,9 @@ [assembly: AssemblyCopyright("© 2017 Gigya Inc.")] [assembly: AssemblyDescription("Microdot Framework")] -[assembly: AssemblyVersion("1.4.2.0")] -[assembly: AssemblyFileVersion("1.4.2.0")] -[assembly: AssemblyInformationalVersion("1.4.2.0")] +[assembly: AssemblyVersion("1.5.0.0")] +[assembly: AssemblyFileVersion("1.5.0.0")] +[assembly: AssemblyInformationalVersion("1.5.0.0")] // Setting ComVisible to false makes the types in this assembly not visible From c39495dfc66a9928bf4bdea3a9fa4a922aac3dc8 Mon Sep 17 00:00:00 2001 From: Allon Guralnek Date: Thu, 31 Aug 2017 15:48:03 +0300 Subject: [PATCH 3/9] Fixed typo. --- Gigya.Microdot.ServiceDiscovery/ConsulDiscoverySource.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gigya.Microdot.ServiceDiscovery/ConsulDiscoverySource.cs b/Gigya.Microdot.ServiceDiscovery/ConsulDiscoverySource.cs index 2b75c96c..6a3b249a 100644 --- a/Gigya.Microdot.ServiceDiscovery/ConsulDiscoverySource.cs +++ b/Gigya.Microdot.ServiceDiscovery/ConsulDiscoverySource.cs @@ -174,7 +174,7 @@ public override Exception AllEndpointsUnreachable(EndPointsResult endPointsResul else if (endPointsResult.Error != null) return new EnvironmentException("Error calling Consul. See tags for details.", unencrypted: tags); else if (endPointsResult.IsQueryDefined == false) - return new EnvironmentException("Query not exists on Consul. See tags for details.", unencrypted: tags); + return new EnvironmentException("Query doesn't exists on Consul. See tags for details.", unencrypted: tags); else return new EnvironmentException("No endpoint were specified in Consul for the requested service.", unencrypted: tags); } From c6d3c7647ac594c720015b06ee3c9c062a6513e5 Mon Sep 17 00:00:00 2001 From: Daniel Lamberger Date: Sun, 3 Sep 2017 10:40:06 +0300 Subject: [PATCH 4/9] Reduced stats events fields precision to 3 digits (1 microsecond resolution) --- Gigya.Microdot.SharedLogic/Events/EventFieldFormatter.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Gigya.Microdot.SharedLogic/Events/EventFieldFormatter.cs b/Gigya.Microdot.SharedLogic/Events/EventFieldFormatter.cs index ccb15353..44986bb9 100644 --- a/Gigya.Microdot.SharedLogic/Events/EventFieldFormatter.cs +++ b/Gigya.Microdot.SharedLogic/Events/EventFieldFormatter.cs @@ -94,11 +94,11 @@ static string SerializeFieldValue(TypeCode tc, object fieldValue) case TypeCode.String: return fieldValue.ToString(); case TypeCode.Single: - return Math.Round((float)fieldValue, 4).ToString(CultureInfo.InvariantCulture); + return Math.Round((float)fieldValue, 3).ToString(CultureInfo.InvariantCulture); case TypeCode.Double: - return Math.Round((double)fieldValue, 4).ToString(CultureInfo.InvariantCulture); + return Math.Round((double)fieldValue, 3).ToString(CultureInfo.InvariantCulture); case TypeCode.Decimal: - return Math.Round((decimal)fieldValue, 4).ToString(CultureInfo.InvariantCulture); + return Math.Round((decimal)fieldValue, 3).ToString(CultureInfo.InvariantCulture); case TypeCode.DateTime: return ((DateTime)fieldValue).ToUniversalTime().ToString("o", CultureInfo.InvariantCulture); case TypeCode.Boolean: From f6445e8160a2c5e8a13d72685d3ed00312772439 Mon Sep 17 00:00:00 2001 From: eran Date: Sun, 3 Sep 2017 14:49:50 +0300 Subject: [PATCH 5/9] Fix ServiceSchema (#79) Fix Bug In ServiceSchema, Handle Return "Task" --- .../HttpService/ServiceSchema.cs | 46 ++++--- .../Properties/AssemblyInfo.cs | 6 +- SolutionVersion.cs | 6 +- .../Gigya.Microdot.UnitTests.csproj | 1 + .../ServiceSchemaTests.cs | 116 ++++++++++++++++++ 5 files changed, 153 insertions(+), 22 deletions(-) create mode 100644 tests/Gigya.Microdot.UnitTests/ServiceSchemaTests.cs diff --git a/Gigya.ServiceContract/HttpService/ServiceSchema.cs b/Gigya.ServiceContract/HttpService/ServiceSchema.cs index 4a8ea583..429b65b2 100644 --- a/Gigya.ServiceContract/HttpService/ServiceSchema.cs +++ b/Gigya.ServiceContract/HttpService/ServiceSchema.cs @@ -42,13 +42,17 @@ public class ServiceSchema { public InterfaceSchema[] Interfaces { get; set; } - public ServiceSchema() {} + public ServiceSchema() { } public ServiceSchema(Type[] interfaces) { Interfaces = interfaces.Select(_ => new InterfaceSchema(_)).ToArray(); } + internal static bool FilterAttributes(Attribute a) + { + return a.GetType().Namespace?.StartsWith("System.Diagnostics") == false && a.GetType().Namespace?.StartsWith("System.Security") == false; + } } @@ -60,7 +64,7 @@ public class InterfaceSchema public MethodSchema[] Methods { get; set; } - public InterfaceSchema() {} + public InterfaceSchema() { } public InterfaceSchema(Type iface) { @@ -71,7 +75,7 @@ public InterfaceSchema(Type iface) Methods = iface.GetMethods().Select(m => new MethodSchema(m)).ToArray(); Attributes = iface .GetCustomAttributes() - .Where(a => a.GetType().Namespace?.StartsWith("System.Diagnostics") == false) + .Where(ServiceSchema.FilterAttributes) .Select(a => new AttributeSchema(a)) .ToArray(); } @@ -98,7 +102,13 @@ public MethodSchema(MethodInfo info) { Name = info.Name; - if (info.ReturnType.IsGenericType && info.ReturnType.GetGenericTypeDefinition()==typeof(Task<>)) + + if (info.ReturnType == typeof(Task)) + { + Response = null; + + } + else if (info.ReturnType.IsGenericType && info.ReturnType.GetGenericTypeDefinition() == typeof(Task<>)) { var resultType = info.ReturnType.GetGenericArguments().Single(); IsRevocable = typeof(IRevocable).IsAssignableFrom(resultType); @@ -109,11 +119,11 @@ public MethodSchema(MethodInfo info) Response = new TypeSchema(info.ReturnType, info.ReturnType.GetCustomAttributes()); } - ResponseType = Response.TypeName; + ResponseType = Response?.TypeName; Parameters = info.GetParameters().Select(p => new ParameterSchema(p)).ToArray(); Attributes = info .GetCustomAttributes() - .Where(a => a.GetType().Namespace?.StartsWith("System.Diagnostics") == false) + .Where(ServiceSchema.FilterAttributes) .Select(a => new AttributeSchema(a)) .ToArray(); } @@ -135,11 +145,13 @@ public SimpleTypeSchema(Type type, IEnumerable attributes) Type = type; TypeName = type.AssemblyQualifiedName; Attributes = attributes - .Where(a => a.GetType().Namespace?.StartsWith("System.Diagnostics") == false) - .Select(a => new AttributeSchema(a)) - .ToArray(); + .Where(ServiceSchema.FilterAttributes) + .Select(a => new AttributeSchema(a)) + .ToArray(); } + + [OnDeserialized] private void OnDeserialized(StreamingContext context) { @@ -151,16 +163,17 @@ private void OnDeserialized(StreamingContext context) } } - public class TypeSchema: SimpleTypeSchema + public class TypeSchema : SimpleTypeSchema { public FieldSchema[] Fields { get; set; } public TypeSchema() { } - public TypeSchema(Type type, IEnumerable attributes): base(type, attributes) + public TypeSchema(Type type, IEnumerable attributes) : base(type, attributes) { if (IsCompositeType(type)) Fields = GetFields(type).ToArray(); + } private IEnumerable GetFields(Type type) @@ -173,21 +186,22 @@ private IEnumerable GetFields(Type type) private bool IsCompositeType(Type type) { + return !type.IsValueType && !(type == typeof(string)); } } - public class ParameterSchema: TypeSchema + public class ParameterSchema : TypeSchema { public string Name { get; set; } public ParameterSchema() { } - public ParameterSchema(ParameterInfo param): this (param.Name, param.ParameterType, param.GetCustomAttributes()) + public ParameterSchema(ParameterInfo param) : this(param.Name, param.ParameterType, param.GetCustomAttributes()) { } - protected ParameterSchema(string name, Type type, IEnumerable attributes): base(type, attributes) + protected ParameterSchema(string name, Type type, IEnumerable attributes) : base(type, attributes) { Name = name; } @@ -221,7 +235,7 @@ public class AttributeSchema public JObject Data { get; set; } - public AttributeSchema() {} + public AttributeSchema() { } public AttributeSchema(Attribute attribute) { @@ -234,7 +248,7 @@ public AttributeSchema(Attribute attribute) private void OnDeserialized(StreamingContext context) { try - { + { Type t = Type.GetType(TypeName); if (t != null) diff --git a/Gigya.ServiceContract/Properties/AssemblyInfo.cs b/Gigya.ServiceContract/Properties/AssemblyInfo.cs index 1983cb2d..888f31ae 100644 --- a/Gigya.ServiceContract/Properties/AssemblyInfo.cs +++ b/Gigya.ServiceContract/Properties/AssemblyInfo.cs @@ -40,9 +40,9 @@ [assembly: AssemblyTrademark("")] -[assembly: AssemblyInformationalVersion("2.4.13")]// if pre-release should be in the format of "2.4.11-pre01". -[assembly: AssemblyVersion("2.4.13")] -[assembly: AssemblyFileVersion("2.4.13")] +[assembly: AssemblyInformationalVersion("2.4.14")]// if pre-release should be in the format of "2.4.11-pre01". +[assembly: AssemblyVersion("2.4.14")] +[assembly: AssemblyFileVersion("2.4.14")] [assembly: AssemblyDescription("")] diff --git a/SolutionVersion.cs b/SolutionVersion.cs index cdfc734e..6770e3a8 100644 --- a/SolutionVersion.cs +++ b/SolutionVersion.cs @@ -28,9 +28,9 @@ [assembly: AssemblyCopyright("© 2017 Gigya Inc.")] [assembly: AssemblyDescription("Microdot Framework")] -[assembly: AssemblyVersion("1.5.0.0")] -[assembly: AssemblyFileVersion("1.5.0.0")] -[assembly: AssemblyInformationalVersion("1.5.0.0")] +[assembly: AssemblyVersion("1.5.1.0")] +[assembly: AssemblyFileVersion("1.5.1.0")] +[assembly: AssemblyInformationalVersion("1.5.1.0")] // Setting ComVisible to false makes the types in this assembly not visible diff --git a/tests/Gigya.Microdot.UnitTests/Gigya.Microdot.UnitTests.csproj b/tests/Gigya.Microdot.UnitTests/Gigya.Microdot.UnitTests.csproj index b9d0b248..c730cbfb 100644 --- a/tests/Gigya.Microdot.UnitTests/Gigya.Microdot.UnitTests.csproj +++ b/tests/Gigya.Microdot.UnitTests/Gigya.Microdot.UnitTests.csproj @@ -84,6 +84,7 @@ + diff --git a/tests/Gigya.Microdot.UnitTests/ServiceSchemaTests.cs b/tests/Gigya.Microdot.UnitTests/ServiceSchemaTests.cs new file mode 100644 index 00000000..df825cf6 --- /dev/null +++ b/tests/Gigya.Microdot.UnitTests/ServiceSchemaTests.cs @@ -0,0 +1,116 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Gigya.Common.Contracts.HttpService; +using Newtonsoft.Json; +using NUnit.Framework; +using Shouldly; + +namespace Gigya.Microdot.UnitTests +{ + [TestFixture] + public class ServiceSchemaTests + { + + [Test] + public void ComplexResponseTypeShouldHaveFieldsWithAttributes() + { + InterfaceSchema schema = new InterfaceSchema(typeof(IHasReturnType)); + schema.Methods.First().Response.Fields.Length.ShouldBe(2); + (schema.Methods.First().Response.Fields.First().Attributes.Single().Attribute is JsonPropertyAttribute).ShouldBeTrue(); + } + + [TestCase(typeof(ISimpleReturnObjectString))] + [TestCase(typeof(ISimpleReturnObject))] + public void SimpleResponseTypeShouldNotHaveFields(Type type) + { + InterfaceSchema schema = new InterfaceSchema(type); + schema.Methods.First().Response.Fields.ShouldBeNull(); + } + + [TestCase(typeof(ISimpleGetter))] + [TestCase(typeof(ISimpleGetterString))] + [TestCase(typeof(ISimpleReturnObject))] + public void RequestParamShouldBeWithoutAttribute(Type type) + { + InterfaceSchema schema = new InterfaceSchema(type); + foreach (var parameter in schema.Methods.First().Parameters) + { + parameter.Attributes.ShouldBeEmpty(); + } + } + + + [TestCase(typeof(ISimpleGetter))] + [TestCase(typeof(ISimpleGetterString))] + [TestCase(typeof(IComplexGetter))] + + public void MethodShouldHaveOneParam(Type type) + { + InterfaceSchema schema = new InterfaceSchema(type); + schema.Methods.First().Parameters.Length.ShouldBe(1); + } + + public void ResponseShouldBeNullForMethodWithoutResponseType() + { + InterfaceSchema schema = new InterfaceSchema(typeof(INoRetrunObject)); + schema.Methods.First().Response.ShouldBeNull(); + + } + + public void ReqestParamWithComplexObjectShouldHaveAttrbute(Type type) + { + InterfaceSchema schema = new InterfaceSchema(type); + schema.Methods.First().Parameters.First().Fields.First().Attributes.Length.ShouldBe(1); + } + + } + + + internal interface ISimpleGetter + { + Task SimpleGet(int someValue); + } + + internal interface ISimpleGetterString + { + Task SimpleGet(string someValue); + } + + internal interface IComplexGetter + { + Task Getter(ComplexType someValue); + } + + internal interface ISimpleReturnObject + { + Task SimpleReturnObject(); + } + + internal interface ISimpleReturnObjectString + { + Task SimpleReturnObject(); + + } + + internal interface INoRetrunObject + { + Task NoRetrunObject(); + } + internal interface IHasReturnType + { + Task HasReturnType(); + } + + + internal class ComplexType + { + [JsonProperty] + + public int HasAttribute { get; set; } + + [JsonProperty] + public int HasAttribute2 { get; set; } + } + +} \ No newline at end of file From f640894f9ea72daaba681bf6a617aa48a9c7842f Mon Sep 17 00:00:00 2001 From: Eran Ofer Date: Sun, 3 Sep 2017 16:03:22 +0300 Subject: [PATCH 6/9] small refactor --- .../HttpService/ServiceSchema.cs | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/Gigya.ServiceContract/HttpService/ServiceSchema.cs b/Gigya.ServiceContract/HttpService/ServiceSchema.cs index 429b65b2..f9ba0aa0 100644 --- a/Gigya.ServiceContract/HttpService/ServiceSchema.cs +++ b/Gigya.ServiceContract/HttpService/ServiceSchema.cs @@ -48,14 +48,8 @@ public ServiceSchema(Type[] interfaces) { Interfaces = interfaces.Select(_ => new InterfaceSchema(_)).ToArray(); } - - internal static bool FilterAttributes(Attribute a) - { - return a.GetType().Namespace?.StartsWith("System.Diagnostics") == false && a.GetType().Namespace?.StartsWith("System.Security") == false; - } } - public class InterfaceSchema { public string Name { get; set; } @@ -75,7 +69,7 @@ public InterfaceSchema(Type iface) Methods = iface.GetMethods().Select(m => new MethodSchema(m)).ToArray(); Attributes = iface .GetCustomAttributes() - .Where(ServiceSchema.FilterAttributes) + .Where(AttributeSchema.FilterAttributes) .Select(a => new AttributeSchema(a)) .ToArray(); } @@ -123,7 +117,7 @@ public MethodSchema(MethodInfo info) Parameters = info.GetParameters().Select(p => new ParameterSchema(p)).ToArray(); Attributes = info .GetCustomAttributes() - .Where(ServiceSchema.FilterAttributes) + .Where(AttributeSchema.FilterAttributes) .Select(a => new AttributeSchema(a)) .ToArray(); } @@ -145,13 +139,11 @@ public SimpleTypeSchema(Type type, IEnumerable attributes) Type = type; TypeName = type.AssemblyQualifiedName; Attributes = attributes - .Where(ServiceSchema.FilterAttributes) + .Where(AttributeSchema.FilterAttributes) .Select(a => new AttributeSchema(a)) .ToArray(); } - - [OnDeserialized] private void OnDeserialized(StreamingContext context) { @@ -234,7 +226,6 @@ public class AttributeSchema public JObject Data { get; set; } - public AttributeSchema() { } public AttributeSchema(Attribute attribute) @@ -256,6 +247,11 @@ private void OnDeserialized(StreamingContext context) } catch { } } + + internal static bool FilterAttributes(Attribute a) + { + return a.GetType().Namespace?.StartsWith("System.Diagnostics") == false && a.GetType().Namespace?.StartsWith("System.Security") == false; + } } } From 0d4533ce0a3ba451bfda563efc7f5321faa4fd3b Mon Sep 17 00:00:00 2001 From: Eran Ofer Date: Sun, 3 Sep 2017 16:09:54 +0300 Subject: [PATCH 7/9] delete conflict file --- SolutionVersion.cs.orig | 47 ----------------------------------------- 1 file changed, 47 deletions(-) delete mode 100644 SolutionVersion.cs.orig diff --git a/SolutionVersion.cs.orig b/SolutionVersion.cs.orig deleted file mode 100644 index ec9998e3..00000000 --- a/SolutionVersion.cs.orig +++ /dev/null @@ -1,47 +0,0 @@ -#region Copyright -// Copyright 2017 Gigya Inc. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -#endregion - -using System; -using System.Reflection; -using System.Runtime.InteropServices; - -[assembly: AssemblyCompany("Gigya Inc.")] -[assembly: AssemblyCopyright("© 2017 Gigya Inc.")] -[assembly: AssemblyDescription("Microdot Framework")] - -<<<<<<< HEAD -[assembly: AssemblyVersion("1.5.1.0")] -[assembly: AssemblyFileVersion("1.5.1.0")] -[assembly: AssemblyInformationalVersion("1.5.1.0")] -======= -[assembly: AssemblyVersion("1.5.0.0")] -[assembly: AssemblyFileVersion("1.5.0.0")] -[assembly: AssemblyInformationalVersion("1.5.0.0")] ->>>>>>> master - - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] -[assembly: CLSCompliant(false)] - From 65ae94e705055a3bc5ce900785b9d5bb5ab9902b Mon Sep 17 00:00:00 2001 From: David Bronshtein Date: Sun, 3 Sep 2017 16:59:06 +0300 Subject: [PATCH 8/9] publish queue request length metric --- .../MetricsStatisticsPublisher.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Gigya.Microdot.Orleans.Hosting/MetricsStatisticsPublisher.cs b/Gigya.Microdot.Orleans.Hosting/MetricsStatisticsPublisher.cs index 46c202d1..3029c2a6 100644 --- a/Gigya.Microdot.Orleans.Hosting/MetricsStatisticsPublisher.cs +++ b/Gigya.Microdot.Orleans.Hosting/MetricsStatisticsPublisher.cs @@ -36,6 +36,7 @@ namespace Gigya.Microdot.Orleans.Hosting internal class MetricsStatisticsPublisher : IConfigurableStatisticsPublisher , IConfigurableSiloMetricsDataPublisher, IConfigurableClientMetricsDataPublisher , IProvider { private readonly ConcurrentDictionary latestMetricValues = new ConcurrentDictionary(); + private long latestRequestQueueLength = 0; /// Contains a set of gauges whose lambda getter methods fetch their values from private readonly MetricsContext context = Metric.Context("Silo"); @@ -82,6 +83,8 @@ private void PublishMetrics(IEnumerable statsCounters) } } } + + context.Gauge("Request queue length", ()=>latestRequestQueueLength, Unit.Items); } public Task Init(bool isSilo, string storageConnectionString, string deploymentId, string address, string siloName, string hostName) @@ -99,9 +102,9 @@ public Task Init(string deploymentId, string storageConnectionString, SiloAddres return TaskDone.Done; } - public Task ReportMetrics(ISiloPerformanceMetrics metricsData) + public async Task ReportMetrics(ISiloPerformanceMetrics metricsData) { - return TaskDone.Done; + latestRequestQueueLength = metricsData.RequestQueueLength; } void IConfigurableSiloMetricsDataPublisher.AddConfiguration(string deploymentId, bool isSilo, string siloName, SiloAddress address, IPEndPoint gateway, string hostName) From c3789161d2dedb1905f9581d3d3992ba7b9b6950 Mon Sep 17 00:00:00 2001 From: David Bronshtein Date: Mon, 4 Sep 2017 09:09:09 +0300 Subject: [PATCH 9/9] fix tests --- .../MetricsStatisticsPublisherTests.cs | 45 ++++++++----------- 1 file changed, 18 insertions(+), 27 deletions(-) diff --git a/tests/Gigya.Microdot.UnitTests/Monitor/MetricsStatisticsPublisherTests.cs b/tests/Gigya.Microdot.UnitTests/Monitor/MetricsStatisticsPublisherTests.cs index d08ebf0f..80a629ea 100644 --- a/tests/Gigya.Microdot.UnitTests/Monitor/MetricsStatisticsPublisherTests.cs +++ b/tests/Gigya.Microdot.UnitTests/Monitor/MetricsStatisticsPublisherTests.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Linq; using System.Net; using Gigya.Microdot.Orleans.Hosting; @@ -12,6 +13,7 @@ using Orleans.Providers; using Orleans.Runtime; +using Shouldly; namespace Gigya.Microdot.UnitTests { @@ -62,20 +64,14 @@ public void ClosePublisherTest() public void PublishEmptyListTest() { publisher.ReportStats(new List()).Wait(); - GetMetricsData().AssertEquals(new MetricsDataEquatable - { - Gauges = new List() - }); + GetMetricsData().Gauges.ShouldNotBeNull(); } [Test] public void PublishNullTest() { publisher.ReportStats(null).Wait(); - GetMetricsData().AssertEquals(new MetricsDataEquatable - { - Gauges = new List() - }); + GetMetricsData().Gauges.ShouldNotBeNull(); } [Test] @@ -89,10 +85,7 @@ public void LogOnlyCounterNotPublishedTest() publisher.ReportStats(new List { counter }).Wait(); - GetMetricsData().AssertEquals(new MetricsDataEquatable - { - Gauges = new List() - }); + GetGauge("LogOnlyCounter").ShouldBeNull(); } [Test] @@ -106,9 +99,7 @@ public void PublishNonDeltaCounterTest() publisher.ReportStats(new List { counter }).Wait(); - var mdata = GetMetricsRepresentation("NonDeltaCounter", 100); - - GetMetricsData().AssertEquals(mdata); + GetGauge("NonDeltaCounter").Value.ShouldBe(100); } [Test] public void UpdateNonDeltaCounterTest() @@ -120,15 +111,13 @@ public void UpdateNonDeltaCounterTest() counter.GetValueString().Returns("100"); publisher.ReportStats(new List { counter }).Wait(); - - var mdata = GetMetricsRepresentation("NonDeltaCounter", 100); - GetMetricsData().AssertEquals(mdata); + + GetGauge("NonDeltaCounter").Value.ShouldBe(100); counter.GetValueString().Returns("300"); publisher.ReportStats(new List { counter }).Wait(); - mdata = GetMetricsRepresentation("NonDeltaCounter", 300); - GetMetricsData().AssertEquals(mdata); + GetGauge("NonDeltaCounter").Value.ShouldBe(300); } [Test] @@ -142,9 +131,7 @@ public void PublishDeltaCounterTest() publisher.ReportStats(new List { counter }).Wait(); - var mdata = GetMetricsRepresentation("DeltaCounter", 100); - - GetMetricsData().AssertEquals(mdata); + GetGauge("DeltaCounter").Value.ShouldBe(100); } [Test] @@ -158,13 +145,11 @@ public void UpdateDeltaCounterTest() publisher.ReportStats(new List { counter }).Wait(); - var mdata = GetMetricsRepresentation("DeltaCounter", 100); - GetMetricsData().AssertEquals(mdata); + GetGauge("DeltaCounter").Value.ShouldBe(100); publisher.ReportStats(new List { counter }).Wait(); - mdata = GetMetricsRepresentation("DeltaCounter", 200); - GetMetricsData().AssertEquals(mdata); + GetGauge("DeltaCounter").Value.ShouldBe(200); } private static MetricsDataEquatable GetMetricsRepresentation(string counterName,long val) @@ -185,6 +170,12 @@ private static MetricsData GetMetricsData() Metric.Context("Silo") .DataProvider.CurrentMetricsData; } + + private static GaugeValueSource GetGauge(string gaugeName) + { + return GetMetricsData().Gauges.FirstOrDefault(g => g.Name == gaugeName); + } + } }