public async Task <string> CompleteDiagnosticObserverTest() { Tracer.Instance = GetTracer(); var builder = new WebHostBuilder() .UseStartup <Startup>(); var testServer = new TestServer(builder); var client = testServer.CreateClient(); var observers = new List <DiagnosticObserver> { new AspNetCoreDiagnosticObserver() }; string retValue = null; using (var diagnosticManager = new DiagnosticManager(observers)) { diagnosticManager.Start(); DiagnosticManager.Instance = diagnosticManager; retValue = await client.GetStringAsync("/Home"); try { await client.GetStringAsync("/Home/error"); } catch { } DiagnosticManager.Instance = null; } return(retValue); }
/// <summary> /// Паттерн "Заместитель" представляет суррогатный объект, управляющий доступом к другому объекту. /// Отличие "Заместителя" от "Декоратора" в том, что первый управляет доступом, а второй расширяет поведение объекта. /// /// Клиентский объект работает так, словно он вызывает методы удаленного объекта. Но в действительности он вызывает /// методы объекта-заместителя, существующего в локальной куче, который берет на себя все низкоуровневые подробности сетевых взаимодействий. /// /// Виды паттерна: /// - удаленный заместитель (управляет взаимодействием клиента с удаленным объектом); /// - виртуальный заместитель (управляет доступом к объекту, создание которого сопряжено с большими затратами); /// - защитный заместитель (управляет доступом к методам объекта в зависимости от привилегий вызывающей стороны); /// - фильтрующий заместитель (управляет доступом к группам сетевых ресурсов, защищая их от "недобросовестных" клиентов); /// - умная ссылка (обеспечивает выполнение дополнительных действий при обращении к объекту (например изменение ссылок счетчика)); /// - кэширующий заместитель (обеспечивает временное хранение результатов высокозатратных операций. /// Также может обеспечивать совместный доступ к результатам для предотвращения лишних вычислений или пересылки данных по сети); /// - синхронизирующий заместитель (предоставляет безопасный доступ к объекту из нескольких программных потоков); /// - упрощающий заместитель (скрывает сложность и управляет доступом к сложному набору классов. Иногда по очевидным соображениям называется фасадным заместителем. /// Упрощающий заместитель отличается от паттерна "Фасад" тем, что первый управляет доступом, а второй только предоставляет альтернативный интерфейс); /// - заместитель отложенного копирования (задерживает фактическое копирование объекта до момента выполнения операции с копией (разновидность виртуального заместителя)). /// </summary> public void DemoProxy() { // Пример применения паттерна "удаленный заместитель" IDiagnosticManager diagnosticManager = new DiagnosticManager(); diagnosticManager.GetSummary("localhost"); }
internal void StartDiagnosticObserversInternal() { DiagnosticManager?.Stop(); var observers = new List <DiagnosticObserver>(); #if NETSTANDARD if (Settings.IsIntegrationEnabled(AspNetCoreDiagnosticObserver.IntegrationName)) { Log.Debug("Adding AspNetCoreDiagnosticObserver"); var aspNetCoreDiagnosticOptions = new AspNetCoreDiagnosticOptions(); observers.Add(new AspNetCoreDiagnosticObserver(this, aspNetCoreDiagnosticOptions)); } #endif if (observers.Count == 0) { Log.Debug("DiagnosticManager not started, zero observers added."); } else { Log.Debug("Starting DiagnosticManager with {0} observers.", observers.Count); var diagnosticManager = new DiagnosticManager(observers); diagnosticManager.Start(); DiagnosticManager = diagnosticManager; } }
public HttpHandlerDiagnosticTest(ITestOutputHelper output) { _tracer = new MockTracer(); _options = new HttpHandlerDiagnosticOptions(); IServiceProvider serviceProvider = new ServiceCollection() .AddLogging(logging => { logging.AddXunit(output); }) .AddOpenTracingCoreServices(builder => { builder.AddCoreFx(); builder.Services.AddSingleton <ITracer>(_tracer); builder.Services.AddSingleton(Options.Create(_options)); }) .BuildServiceProvider(); _diagnosticsManager = serviceProvider.GetRequiredService <DiagnosticManager>(); _diagnosticsManager.Start(); // Inner handler for mocking the result _httpHandler = new MockHttpMessageHandler(); // Wrap with DiagnosticsHandler (which is internal :( ) Type type = typeof(HttpClientHandler).Assembly.GetType("System.Net.Http.DiagnosticsHandler"); ConstructorInfo constructor = type.GetConstructors(BindingFlags.Instance | BindingFlags.Public)[0]; HttpMessageHandler diagnosticsHandler = (HttpMessageHandler)constructor.Invoke(new object[] { _httpHandler }); _httpClient = new HttpClient(diagnosticsHandler); }
public void EmptyDiagnosticManagerConfigurationIsEmptyByDefault() { var configuration = new EmptyDiagnosticManagerConfiguration(); Assert.IsNotNull(configuration); var diagnosticManager = new DiagnosticManager(configuration); Assert.IsNotNull(diagnosticManager); Assert.IsTrue(!diagnosticManager.Providers.Any()); }
private static void StartDiagnosticManager() { var observers = new List <DiagnosticObserver> { new AspNetCoreDiagnosticObserver() }; var diagnosticManager = new DiagnosticManager(observers); diagnosticManager.Start(); DiagnosticManager.Instance = diagnosticManager; }
public void EmptyDiagnosticManagerConfigurationReturnsEmptyDiagnosticReport() { var configuration = new EmptyDiagnosticManagerConfiguration(); Assert.IsNotNull(configuration); var diagnosticManager = new DiagnosticManager(configuration); Assert.IsNotNull(diagnosticManager); Assert.IsTrue(!diagnosticManager.Providers.Any()); var diagnosticReport = diagnosticManager.GetReports(); Assert.IsNotNull(diagnosticReport); Assert.IsTrue(!diagnosticReport.Reports.Any()); }
public HostingTest(ITestOutputHelper output) { _tracer = new MockTracer(); var aspNetCoreOptions = new AspNetCoreDiagnosticOptions(); _options = aspNetCoreOptions.Hosting; _serviceProvider = new ServiceCollection() .AddLogging(logging => { logging.AddXunit(output); logging.AddFilter("OpenTracing", LogLevel.Trace); }) .AddOpenTracingCoreServices(builder => { builder.AddAspNetCore(); builder.Services.AddSingleton <ITracer>(_tracer); builder.Services.AddSingleton(Options.Create(aspNetCoreOptions)); }) .BuildServiceProvider(); _diagnosticManager = _serviceProvider.GetRequiredService <DiagnosticManager>(); _diagnosticManager.Start(); // Request _httpContext = new DefaultHttpContext(); SetRequest(); // Hosting Application var diagnosticSource = new DiagnosticListener("Microsoft.AspNetCore"); _features = new FeatureCollection(); _features.Set <IHttpRequestFeature>(new HttpRequestFeature()); var httpContextFactory = Substitute.For <IHttpContextFactory>(); httpContextFactory.Create(_features).Returns(_httpContext); _hostingApplication = new HostingApplication( ctx => Task.FromResult(0), _serviceProvider.GetRequiredService <ILogger <HostingTest> >(), diagnosticSource, httpContextFactory); }
public void Start_if_valid_Tracer() { var loggerFactory = new NullLoggerFactory(); var tracer = new MockTracer(); var diagnosticSubscribers = new List <DiagnosticObserver>(); var options = Options.Create(new DiagnosticManagerOptions()); using (DiagnosticManager diagnosticManager = new DiagnosticManager(loggerFactory, tracer, diagnosticSubscribers, options)) { Assert.False(diagnosticManager.IsRunning); diagnosticManager.Start(); Assert.True(diagnosticManager.IsRunning); } }
public void Does_not_Start_if_Tracer_is_GlobalTracer_with_NoopTracer() { var loggerFactory = new NullLoggerFactory(); var tracer = GlobalTracer.Instance; var diagnosticSubscribers = new List <DiagnosticObserver>(); var options = Options.Create(new DiagnosticManagerOptions()); using (DiagnosticManager diagnosticManager = new DiagnosticManager(loggerFactory, tracer, diagnosticSubscribers, options)) { Assert.False(diagnosticManager.IsRunning); diagnosticManager.Start(); Assert.False(diagnosticManager.IsRunning); } }
private static void StartDiagnosticManager() { var observers = new List <DiagnosticObserver>(); if (!PlatformHelpers.AzureAppServices.Metadata.IsFunctionsApp) { // Not adding the `AspNetCoreDiagnosticObserver` is particularly important for Azure Functions. // The AspNetCoreDiagnosticObserver will be loaded in a separate Assembly Load Context, breaking the connection of AsyncLocal // This is because user code is loaded within the functions host in a separate context observers.Add(new AspNetCoreDiagnosticObserver()); } var diagnosticManager = new DiagnosticManager(observers); diagnosticManager.Start(); DiagnosticManager.Instance = diagnosticManager; }
public InstrumentationService(DiagnosticManager diagnosticManager) { _diagnosticManager = diagnosticManager ?? throw new ArgumentNullException(nameof(diagnosticManager)); }
private static async Task AssertDiagnosticObserverSubmitsSpans <T>( string path, HttpStatusCode statusCode, bool isError, string resourceName, SerializableDictionary expectedParentSpanTags, bool featureFlag = false, int spanCount = 1, string childSpan1ResourceName = null, SerializableDictionary firstChildSpanTags = null, string childSpan2ResourceName = null, SerializableDictionary secondChildSpanTags = null) where T : class { var writer = new AgentWriterStub(); var configSource = new NameValueConfigurationSource(new NameValueCollection { { ConfigurationKeys.FeatureFlags.RouteTemplateResourceNamesEnabled, featureFlag.ToString() }, }); var tracer = GetTracer(writer, configSource); var builder = new WebHostBuilder() .UseStartup <T>(); var testServer = new TestServer(builder); var client = testServer.CreateClient(); var observers = new List <DiagnosticObserver> { new AspNetCoreDiagnosticObserver(tracer) }; using (var diagnosticManager = new DiagnosticManager(observers)) { diagnosticManager.Start(); try { var response = await client.GetAsync(path); Assert.Equal(statusCode, response.StatusCode); } catch (Exception ex) { Assert.True(isError, $"Unexpected error calling endpoint: {ex}"); } // The diagnostic observer runs on a separate thread // This gives time for the Stop event to run and to be flushed to the writer const int timeoutInMilliseconds = 10000; var deadline = DateTime.Now.AddMilliseconds(timeoutInMilliseconds); while (DateTime.Now < deadline) { if (writer.Traces.Count > 0) { break; } Thread.Sleep(200); } } var trace = Assert.Single(writer.Traces); trace.Should().HaveCount(spanCount); var parentSpan = trace.Should() .ContainSingle(x => x.OperationName == "aspnet_core.request") .Subject; AssertTagHasValue(parentSpan, Tags.InstrumentationName, "aspnet_core"); parentSpan.Type.Should().Be(SpanTypes.Web); parentSpan.ResourceName.Should().Be(resourceName); AssertTagHasValue(parentSpan, Tags.SpanKind, SpanKinds.Server); AssertTagHasValue(parentSpan, Tags.Language, TracerConstants.Language); AssertTagHasValue(parentSpan, Tags.HttpStatusCode, ((int)statusCode).ToString()); parentSpan.Error.Should().Be(isError); if (expectedParentSpanTags is not null) { foreach (var expectedTag in expectedParentSpanTags.Values) { AssertTagHasValue(parentSpan, expectedTag.Key, expectedTag.Value); } } if (spanCount > 1) { trace.Should().Contain(x => x.OperationName == "aspnet_core_mvc.request"); var childSpan = trace.First(x => x.OperationName == "aspnet_core_mvc.request"); AssertTagHasValue(childSpan, Tags.InstrumentationName, "aspnet_core"); childSpan.Type.Should().Be(SpanTypes.Web); childSpan.ResourceName.Should().Be(childSpan1ResourceName ?? resourceName); AssertTagHasValue(childSpan, Tags.SpanKind, SpanKinds.Server); AssertTagHasValue(childSpan, Tags.Language, TracerConstants.Language); if (firstChildSpanTags is not null) { foreach (var expectedTag in firstChildSpanTags.Values) { AssertTagHasValue(childSpan, expectedTag.Key, expectedTag.Value); } } if (spanCount > 2) { var childSpan2 = trace.Last(x => x.OperationName == "aspnet_core_mvc.request"); childSpan2.Should().NotBe(childSpan); AssertTagHasValue(childSpan2, Tags.InstrumentationName, "aspnet_core"); childSpan2.Type.Should().Be(SpanTypes.Web); childSpan2.ResourceName.Should().Be(childSpan2ResourceName); AssertTagHasValue(childSpan2, Tags.SpanKind, SpanKinds.Server); AssertTagHasValue(childSpan2, Tags.Language, TracerConstants.Language); if (secondChildSpanTags is not null) { foreach (var expectedTag in secondChildSpanTags.Values) { AssertTagHasValue(childSpan2, expectedTag.Key, expectedTag.Value); } } } } }
public InstrumentationService(DiagnosticManager diagnosticManager) { _diagnosticsManager = diagnosticManager ?? throw new ArgumentNullException(nameof(diagnosticManager)); Status = HostedServiceStatus.Created; }