Additional statistics when a ServiceProvider is created (#58030)
authorgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Tue, 24 Aug 2021 20:50:27 +0000 (13:50 -0700)
committerGitHub <noreply@github.com>
Tue, 24 Aug 2021 20:50:27 +0000 (13:50 -0700)
* Number of open generics
* Number of closed generics

fix #52364

Co-authored-by: Allan Targino <13934447+allantargino@users.noreply.github.com>
src/libraries/Microsoft.Extensions.DependencyInjection/src/DependencyInjectionEventSource.cs
src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/DependencyInjectionEventSourceTests.cs

index 338325e..03b2452 100644 (file)
@@ -79,9 +79,9 @@ namespace Microsoft.Extensions.DependencyInjection
         [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
             Justification = "Parameters to this method are primitive and are trimmer safe.")]
         [Event(7, Level = EventLevel.Informational, Keywords = Keywords.ServiceProviderInitialized)]
-        private void ServiceProviderBuilt(int serviceProviderHashCode, int singletonServices, int scopedServices, int transientServices)
+        private void ServiceProviderBuilt(int serviceProviderHashCode, int singletonServices, int scopedServices, int transientServices, int closedGenericsServices, int openGenericsServices)
         {
-            WriteEvent(7, serviceProviderHashCode, singletonServices, scopedServices, transientServices);
+            WriteEvent(7, serviceProviderHashCode, singletonServices, scopedServices, transientServices, closedGenericsServices, openGenericsServices);
         }
 
         [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
@@ -174,6 +174,8 @@ namespace Microsoft.Extensions.DependencyInjection
                 int singletonServices = 0;
                 int scopedServices = 0;
                 int transientServices = 0;
+                int closedGenericsServices = 0;
+                int openGenericsServices = 0;
 
                 StringBuilder descriptorBuilder = new StringBuilder("{ \"descriptors\":[ ");
                 bool firstDescriptor = true;
@@ -202,11 +204,23 @@ namespace Microsoft.Extensions.DependencyInjection
                             transientServices++;
                             break;
                     }
+
+                    if (descriptor.ServiceType.IsGenericType)
+                    {
+                        if (descriptor.ServiceType.IsConstructedGenericType)
+                        {
+                            closedGenericsServices++;
+                        }
+                        else
+                        {
+                            openGenericsServices++;
+                        }
+                    }
                 }
                 descriptorBuilder.Append(" ] }");
 
                 int providerHashCode = provider.GetHashCode();
-                ServiceProviderBuilt(providerHashCode, singletonServices, scopedServices, transientServices);
+                ServiceProviderBuilt(providerHashCode, singletonServices, scopedServices, transientServices, closedGenericsServices, openGenericsServices);
 
                 string descriptorString = descriptorBuilder.ToString();
                 int chunkCount = descriptorString.Length / MaxChunkSize + (descriptorString.Length % MaxChunkSize > 0 ? 1 : 0);
index 11d8ae9..deaaba5 100644 (file)
@@ -241,14 +241,18 @@ namespace Microsoft.Extensions.DependencyInjection.Tests
             serviceCollection.AddScoped<IFakeMultipleService, FakeDisposableCallbackInnerService>();
             serviceCollection.AddTransient<IFakeMultipleService, FakeDisposableCallbackInnerService>();
             serviceCollection.AddSingleton<IFakeService, FakeDisposableCallbackInnerService>();
+            serviceCollection.AddScoped(typeof(IFakeOpenGenericService<>), typeof(FakeOpenGenericService<>));
+            serviceCollection.AddTransient<IFakeOpenGenericService<PocoClass>, FakeOpenGenericService<PocoClass>>();
 
             using ServiceProvider provider = serviceCollection.BuildServiceProvider();
 
             EventWrittenEventArgs serviceProviderBuiltEvent = _listener.EventData.Single(e => e.EventName == "ServiceProviderBuilt");
             GetProperty<int>(serviceProviderBuiltEvent, "serviceProviderHashCode"); // assert hashcode exists as an int
             Assert.Equal(4, GetProperty<int>(serviceProviderBuiltEvent, "singletonServices"));
-            Assert.Equal(1, GetProperty<int>(serviceProviderBuiltEvent, "scopedServices"));
-            Assert.Equal(2, GetProperty<int>(serviceProviderBuiltEvent, "transientServices"));
+            Assert.Equal(2, GetProperty<int>(serviceProviderBuiltEvent, "scopedServices"));
+            Assert.Equal(3, GetProperty<int>(serviceProviderBuiltEvent, "transientServices"));
+            Assert.Equal(1, GetProperty<int>(serviceProviderBuiltEvent, "closedGenericsServices"));
+            Assert.Equal(1, GetProperty<int>(serviceProviderBuiltEvent, "openGenericsServices"));
             Assert.Equal(7, serviceProviderBuiltEvent.EventId);
 
             EventWrittenEventArgs serviceProviderDescriptorsEvent = _listener.EventData.Single(e => e.EventName == "ServiceProviderDescriptors");
@@ -290,6 +294,16 @@ namespace Microsoft.Extensions.DependencyInjection.Tests
                 "      \"serviceType\": \"Microsoft.Extensions.DependencyInjection.Specification.Fakes.IFakeService\",",
                 "      \"lifetime\": \"Singleton\",",
                 "      \"implementationType\": \"Microsoft.Extensions.DependencyInjection.Specification.Fakes.FakeDisposableCallbackInnerService\"",
+                "    },",
+                "    {",
+                "      \"serviceType\": \"Microsoft.Extensions.DependencyInjection.Specification.Fakes.IFakeOpenGenericService`1[TValue]\",",
+                "      \"lifetime\": \"Scoped\",",
+                "      \"implementationType\": \"Microsoft.Extensions.DependencyInjection.Specification.Fakes.FakeOpenGenericService`1[TVal]\"",
+                "    },",
+                "    {",
+                "      \"serviceType\": \"Microsoft.Extensions.DependencyInjection.Specification.Fakes.IFakeOpenGenericService`1[Microsoft.Extensions.DependencyInjection.Specification.Fakes.PocoClass]\",",
+                "      \"lifetime\": \"Transient\",",
+                "      \"implementationType\": \"Microsoft.Extensions.DependencyInjection.Specification.Fakes.FakeOpenGenericService`1[Microsoft.Extensions.DependencyInjection.Specification.Fakes.PocoClass]\"",
                 "    }",
                 "  ]",
                 "}"),