/// <summary> /// OnMethodBegin callback /// </summary> /// <typeparam name="TTarget">Type of the target</typeparam> /// <param name="instance">Instance value, aka `this` of the instrumented method.</param> /// <returns>Calltarget state value</returns> public static CallTargetState GetResponse_OnMethodBegin <TTarget>(TTarget instance) { if (instance is HttpWebRequest request && IsTracingEnabled(request)) { Tracer tracer = Tracer.Instance; // Check if any headers were injected by a previous call to GetRequestStream var spanContext = tracer.Propagator.Extract(request.Headers.Wrap()); Scope scope = null; try { scope = ScopeFactory.CreateOutboundHttpScope(tracer, request.Method, request.RequestUri, IntegrationId, out var tags, spanContext?.SpanId); if (scope != null) { // add distributed tracing headers to the HTTP request tracer.Propagator.Inject(scope.Span.Context, request.Headers.Wrap()); return(new CallTargetState(scope)); } } catch { scope?.Dispose(); throw; } } return(CallTargetState.GetDefault()); }
internal static CallTargetReturn EndInvocationVoid(Exception exception, Scope scope, ILambdaExtensionRequest requestBuilder) { scope?.Dispose(); Flush(); NotifyExtensionEnd(requestBuilder, scope, exception != null); return(CallTargetReturn.GetDefault()); }
private void OnBeginRequest(object sender, EventArgs eventArgs) { Scope scope = null; try { var tracer = Tracer.Instance; if (!tracer.Settings.IsIntegrationEnabled(IntegrationName)) { // integration disabled return; } var httpContext = (sender as HttpApplication)?.Context; if (httpContext == null) { return; } HttpRequest httpRequest = httpContext.Request; SpanContext propagatedContext = null; if (tracer.ActiveScope == null) { try { // extract propagated http headers var headers = httpRequest.Headers.Wrap(); propagatedContext = SpanContextPropagator.Instance.Extract(headers); } catch (Exception ex) { Log.Error(ex, "Error extracting propagated HTTP headers."); } } string host = httpRequest.Headers.Get("Host"); string httpMethod = httpRequest.HttpMethod.ToUpperInvariant(); string url = httpRequest.RawUrl.ToLowerInvariant(); string path = UriHelpers.GetRelativeUrl(httpRequest.Url, tryRemoveIds: true); string resourceName = $"{httpMethod} {path.ToLowerInvariant()}"; scope = tracer.StartActive(_requestOperationName, propagatedContext); scope.Span.DecorateWebServerSpan(resourceName, httpMethod, host, url); // set analytics sample rate if enabled var analyticsSampleRate = tracer.Settings.GetIntegrationAnalyticsSampleRate(IntegrationName, enabledWithGlobalSetting: true); scope.Span.SetMetric(Tags.Analytics, analyticsSampleRate); httpContext.Items[_httpContextScopeKey] = scope; } catch (Exception ex) { // Dispose here, as the scope won't be in context items and won't get disposed on request end in that case... scope?.Dispose(); Log.Error(ex, "Datadog ASP.NET HttpModule instrumentation error"); } }
/// <summary> /// Dispose the scope and container /// </summary> public void Dispose() { // When startup was called, but shutdown not, do this now if (_isStartedUp && !_isShutDown) { // Auto shutdown using (new NoSynchronizationContextScope()) { try { ShutdownAsync().Wait(); } catch (AggregateException ex) { throw ex.GetBaseException(); } } } if (_disposables.Count > 0) { var reversedDisposables = _disposables.Reverse().Where(disposable => disposable != null).ToList(); _disposables.Clear(); foreach (var disposable in reversedDisposables) { disposable?.Dispose(); } } Scope?.Dispose(); Container?.Dispose(); Resolver.Dispose(); }
internal static TReturn EndInvocationAsync <TReturn>(TReturn returnValue, Exception exception, Scope scope, ILambdaExtensionRequest requestBuilder) { scope?.Dispose(); Flush(); NotifyExtensionEnd(requestBuilder, exception != null); return(returnValue); }
protected virtual void Dispose(bool disposing) { if (disposing) { Scope?.Dispose(); } }
public static bool EndInvokeAction(object asyncControllerActionInvoker, object asyncResult, int opCode, int mdToken) { Scope scope = null; var httpContext = HttpContext.Current; try { scope = httpContext?.Items[HttpContextKey] as Scope; } catch (Exception ex) { Log.ErrorException("Error instrumenting method {0}", ex, $"{AsyncActionInvokerTypeName}.EndInvokeAction()"); } var endInvokeAction = Emit.DynamicMethodBuilder <Func <object, object, bool> > .GetOrCreateMethodCallDelegate( AsyncActionInvokerType, "EndInvokeAction", (OpCodeValue)opCode); try { // call the original method, inspecting (but not catching) any unhandled exceptions return(endInvokeAction(asyncControllerActionInvoker, asyncResult)); } catch (Exception ex) when(scope?.Span.SetExceptionForFilter(ex) ?? false) { // unreachable code throw; } finally { scope?.Dispose(); } }
public static bool EndInvokeAction(dynamic asyncControllerActionInvoker, dynamic asyncResult) { Scope scope = null; var httpContext = HttpContext.Current; try { scope = httpContext?.Items[HttpContextKey] as Scope; } catch (Exception ex) { Log.ErrorException("Error instrumenting method {0}", ex, "System.Web.Mvc.Async.IAsyncActionInvoker.EndInvokeAction()"); } try { // call the original method, inspecting (but not catching) any unhandled exceptions return((bool)asyncControllerActionInvoker.EndInvokeAction(asyncResult)); } catch (Exception ex) when(scope?.Span.SetExceptionForFilter(ex) ?? false) { // unreachable code throw; } finally { scope?.Dispose(); } }
public void Dispose() { HealthManager.OnDead -= MobRebirth_OnDead; HealthManager.OnGotDamage -= OnDecreaseHP; AIManager.OnStateChanged -= AIManager_OnStateChanged; Scope?.Dispose(); }
/// <inheritdoc/> protected override void Dispose(bool disposing) { if (disposing) { MemoryBuffer?.Dispose(); Scope?.Dispose(); } base.Dispose(disposing); }
internal static TReturn EndInvocationAsync <TReturn>(TReturn returnValue, Exception exception, Scope scope, ILambdaExtensionRequest requestBuilder) { var json = SerializeObject(returnValue); Flush(); NotifyExtensionEnd(requestBuilder, scope, exception != null, json); scope?.Dispose(); return(returnValue); }
protected virtual void Dispose(bool disposing) { if (View != null) { View.Closed -= View_Closed; View.Close(); } viewLocator.Views.Remove(this); Scope?.Dispose(); }
/// <summary> /// 析构 /// </summary> public void Dispose() { if (IsDisposed) { return; } IsDisposed = true; Command?.Dispose(); Scope?.Dispose(); }
public static bool EndInvokeAction( object asyncControllerActionInvoker, object asyncResult, int opCode, int mdToken, long moduleVersionPtr) { Scope scope = null; var httpContext = HttpContext.Current; try { scope = httpContext?.Items[HttpContextKey] as Scope; } catch (Exception ex) { Log.ErrorException("Error instrumenting method {0}", ex, $"{AsyncActionInvokerTypeName}.EndInvokeAction()"); } Func <object, object, bool> instrumentedMethod; try { var asyncActionInvokerType = asyncControllerActionInvoker.GetInstrumentedInterface(AsyncActionInvokerTypeName); instrumentedMethod = MethodBuilder <Func <object, object, bool> > .Start(moduleVersionPtr, mdToken, opCode, nameof(EndInvokeAction)) .WithConcreteType(asyncActionInvokerType) .WithParameters(asyncResult) .WithNamespaceAndNameFilters(ClrNames.Bool, ClrNames.IAsyncResult) .Build(); } catch (Exception ex) { Log.ErrorException($"Error resolving {AsyncActionInvokerTypeName}.{nameof(EndInvokeAction)}(...)", ex); throw; } try { // call the original method, inspecting (but not catching) any unhandled exceptions return(instrumentedMethod(asyncControllerActionInvoker, asyncResult)); } catch (Exception ex) { scope?.Span.SetException(ex); throw; } finally { scope?.Dispose(); } }
public override void DisposeScope() { // IMPORTANT: HACK to create fake http context for job to allow the LightInject PerWebRequestScopeManager to work correctly when running in background jobs // Umbraco is hardcoded to using MixedLightInjectScopeManagerProvider so its really really hard to get around so this hack is the easiest way to handle this. if (HttpContext.Current == null) { HttpContext.Current = new HttpContext(new HttpRequest("PerWebRequestScopeManager", "https://localhost/PerWebRequestScopeManager", string.Empty), new HttpResponse(new StringWriter())); } _scope?.Dispose(); }
private void OnBeginRequest(object sender, EventArgs eventArgs) { var tracer = Tracer.Instance; if (!tracer.Settings.IsIntegrationEnabled(IntegrationName)) { // integration disabled return; } Scope scope = null; try { if (!TryGetContext(sender, out var httpContext)) { return; } SpanContext propagatedContext = null; if (tracer.ActiveScope == null) { try { // extract propagated http headers var headers = httpContext.Request.Headers.Wrap(); propagatedContext = SpanContextPropagator.Instance.Extract(headers); } catch (Exception ex) { Log.ErrorException("Error extracting propagated HTTP headers.", ex); } } scope = tracer.StartActive(_operationName, propagatedContext); // set analytics sample rate if enabled var analyticsSampleRate = tracer.Settings.GetIntegrationAnalyticsSampleRate(IntegrationName, enabledWithGlobalSetting: true); scope.Span.SetMetric(Tags.Analytics, analyticsSampleRate); httpContext.Items[_httpContextDelegateKey] = HttpContextSpanIntegrationDelegate.CreateAndBegin(httpContext, scope); } catch (Exception ex) { // Dispose here, as the scope won't be in context items and won't get disposed on request end in that case... scope?.Dispose(); Log.ErrorException("Datadog ASP.NET HttpModule instrumentation error", ex); } }
/// <summary> /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// </summary> public void Dispose() { try { if (_httpContext != null) { _scope?.Span?.SetTag("http.status_code", _httpContext.Response.StatusCode.ToString()); } } finally { _scope?.Dispose(); } }
protected virtual void Dispose(bool disposing) { if (!disposedValue) { if (disposing) { HttpContext.Request.RequestStream.Close(); HttpContext.Response.ResponseStream.Close(); Scope?.Dispose(); Thread.CurrentPrincipal = null; } disposedValue = true; } }
protected virtual void Dispose(bool disposing) { if (isDisposed) { return; } if (disposing) { View.Closed -= View_Closed; Scope?.Dispose(); Disposed?.Invoke(); } isDisposed = true; }
/// <summary> /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// </summary> public void Dispose() { try { if (_httpContext != null && _httpContext.TryGetPropertyValue("Response", out object response) && response.TryGetPropertyValue("StatusCode", out object statusCode)) { _scope?.Span?.SetTag("http.status_code", statusCode.ToString()); } } finally { _scope?.Dispose(); } }
public void Dispose_ListWithOneItem_DisposesItem() { // Arrange var scope = new Scope(); var disposable = new DisposableObject(); Assert.IsFalse(disposable.IsDisposedOnce, "Test setup"); var disposables = new List<IDisposable> { disposable }; scope.RegisterForDisposal(disposable); // Act scope.Dispose(); // Assert Assert.IsTrue(disposable.IsDisposedOnce); }
/// <summary> /// OnMethodBegin callback /// </summary> /// <typeparam name="TTarget">Type of the target</typeparam> /// <param name="instance">Instance value, aka `this` of the instrumented method.</param> /// <returns>Calltarget state value</returns> public static CallTargetState GetResponse_OnMethodBegin <TTarget>(TTarget instance) { if (instance is HttpWebRequest request && IsTracingEnabled(request)) { Tracer tracer = Tracer.Instance; // Check if any headers were injected by a previous call to GetRequestStream var spanContext = SpanContextPropagator.Instance.Extract(request.Headers.Wrap()); // If this operation creates the trace, then we need to re-apply the sampling priority bool setSamplingPriority = spanContext?.SamplingPriority != null && tracer.ActiveScope == null; Scope scope = null; try { scope = ScopeFactory.CreateOutboundHttpScope(tracer, request.Method, request.RequestUri, IntegrationId, out _, spanContext?.TraceId, spanContext?.SpanId); if (scope != null) { if (setSamplingPriority && spanContext?.SamplingPriority is not null) { scope.Span.SetTraceSamplingPriority(spanContext.SamplingPriority.Value); } // add distributed tracing headers to the HTTP request SpanContextPropagator.Instance.Inject(scope.Span.Context, request.Headers.Wrap()); tracer.TracerManager.Telemetry.IntegrationGeneratedSpan(IntegrationId); return(new CallTargetState(scope)); } } catch { scope?.Dispose(); throw; } } return(CallTargetState.GetDefault()); }
/// <summary> /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// </summary> public void Dispose() { try { // sometimes, if an exception was unhandled in user code, status code is set to 500 later in the pipeline, // so it is still 200 here. if there was an unhandled exception, always set status code to 500. if (_scope?.Span?.Error == true) { _scope?.Span?.SetTag(Tags.HttpStatusCode, "500"); } else if (_httpContext != null) { _scope?.Span?.SetTag(Tags.HttpStatusCode, _httpContext.Response.StatusCode.ToString()); } } finally { _scope?.Dispose(); } }
public void Dispose_MultipleItems_DisposesAllItems() { // Arrange var scope = new Scope(); var disposables = new List<DisposableObject> { new DisposableObject(), new DisposableObject(), new DisposableObject() }; disposables.ForEach(scope.RegisterForDisposal); // Act scope.Dispose(); // Assert Assert.IsTrue(disposables.All(d => d.IsDisposedOnce)); }
private void OnBeginRequest(object sender, EventArgs eventArgs) { Scope scope = null; try { if (!TryGetContext(sender, out var httpContext)) { return; } SpanContext propagatedContext = null; if (Tracer.Instance.ActiveScope == null) { try { // extract propagated http headers var headers = httpContext.Request.Headers.Wrap(); propagatedContext = SpanContextPropagator.Instance.Extract(headers); } catch (Exception ex) { Log.ErrorException("Error extracting propagated HTTP headers.", ex); } } scope = Tracer.Instance.StartActive(_operationName, propagatedContext); httpContext.Items[_httpContextDelegateKey] = HttpContextSpanIntegrationDelegate.CreateAndBegin(httpContext, scope); } catch (Exception ex) { // Dispose here, as the scope won't be in context items and won't get disposed on request end in that case... scope?.Dispose(); Log.ErrorException("Datadog ASP.NET HttpModule instrumentation error", ex); } }
private static object ApplyResolveScope(InitializationContext context, Func<object> getInstance) { var threadLocal = (ThreadLocal<Scope>)context.Registration.Container.GetItem(Key); var original = threadLocal.Value; var current = new Scope(); try { threadLocal.Value = current; return getInstance(); } finally { try { current.Dispose(); } finally { threadLocal.Value = original; } } }
public override void DisposeScope() { _scope?.Dispose(); }
public void Dispose_RecursiveResolveTriggeredDuringEndScopeAction_ThrowsDescriptiveException() { // Arrange var scope = new Scope(); var scopedLifestyle = new FakeScopedLifestyle(scope); var container = new Container(); container.Register<IPlugin>(() => { scope.WhenScopeEnds(() => { container.GetInstance<IPlugin>(); }); return new DisposablePlugin(); }); container.GetInstance<IPlugin>(); // Act Action action = () => scope.Dispose(); // Assert AssertThat.ThrowsWithExceptionMessageContains<ActivationException>(@" The registered delegate for type IPlugin threw an exception. A recursive registration of Action or IDisposable instances was detected during disposal of the scope. This is possibly caused by a component that is directly or indirectly depending on itself" .TrimInside(), action); }
public void Dispose_WithThrowingAction_StillDisposesInstance() { // Arrange bool disposed = false; var scope = new Scope(); scope.WhenScopeEnds(() => { throw new Exception(); }); scope.RegisterForDisposal(new DisposableObject(_ => { disposed = true; })); try { // Act scope.Dispose(); // Assert Assert.Fail("Exception expected."); } catch { Assert.IsTrue(disposed); } }
public void Dispose_RecursiveResolveTriggeredInDispose_ThrowsDescriptiveException() { // Arrange var scope = new Scope(); var scopedLifestyle = new FakeScopedLifestyle(scope); var container = new Container(); container.Register<IPlugin>(() => { var plugin = new DisposablePlugin(disposing: _ => { // Recursive dependency // Although really bad practice, this must not cause an infinit spin or a stackoverflow. container.GetInstance<IPlugin>(); }); scope.RegisterForDisposal(plugin); return plugin; }); container.GetInstance<IPlugin>(); // Act Action action = () => scope.Dispose(); // Assert AssertThat.ThrowsWithExceptionMessageContains<ActivationException>(@" The registered delegate for type IPlugin threw an exception. A recursive registration of Action or IDisposable instances was detected during disposal of the scope. This is possibly caused by a component that is directly or indirectly depending on itself" .TrimInside(), action); }
public void Dispose_WithMultipleItemsThatThrow_StillDisposesAllItems() { // Arrange var scope = new Scope(); var disposables = new List<DisposableObject> { new DisposableObject(new Exception()), new DisposableObject(new Exception()), new DisposableObject(new Exception()) }; disposables.ForEach(scope.RegisterForDisposal); try { // Act scope.Dispose(); // Assert Assert.Fail("Exception was expected to bubble up."); } catch { Assert.IsTrue(disposables.All(d => d.IsDisposedOnce)); } }
public void Dispose() { _scope?.Dispose(); _container?.Dispose(); }
public void Dispose_ScopedInstanceResolvedDuringDisposingScope_CreatesInstanceWithExpectedLifestyle() { // Arrange IPlugin plugin1 = null; IPlugin plugin2 = null; var scope = new Scope(); var scopedLifestyle = new FakeScopedLifestyle(scope); var container = new Container(); container.Register<IPlugin>(() => new DisposablePlugin(), scopedLifestyle); container.Register<DisposableObject>(() => new DisposableObject(disposing: _ => { plugin1 = container.GetInstance<IPlugin>(); plugin2 = container.GetInstance<IPlugin>(); }), scopedLifestyle); container.GetInstance<DisposableObject>(); // Act scope.Dispose(); // Assert Assert.IsNotNull(plugin1); Assert.AreSame(plugin1, plugin2); }
public void Dispose_MultipleItems_DisposesAllItemsInReversedOrder() { // Arrange var scope = new Scope(); var disposedItems = new List<DisposableObject>(); var disposables = new List<DisposableObject> { new DisposableObject(disposedItems.Add), new DisposableObject(disposedItems.Add), new DisposableObject(disposedItems.Add) }; disposables.ForEach(scope.RegisterForDisposal); // Act scope.Dispose(); disposedItems.Reverse(); // Assert Assert.IsTrue(disposedItems.SequenceEqual(disposables)); }
public void Dispose_WithMultipleItemsThatThrow_WillBubbleUpTheLastThrownException() { // Arrange var scope = new Scope(); Exception lastThrownException = new Exception(); var disposables = new List<DisposableObject> { // Since the objects are disposed in reverse order, the first object is disposed last, and // this exception is expected to bubble up. new DisposableObject(exceptionToThrow: lastThrownException), new DisposableObject(exceptionToThrow: new Exception()), new DisposableObject(exceptionToThrow: new Exception()), new DisposableObject(), new DisposableObject(exceptionToThrow: new Exception()), new DisposableObject(exceptionToThrow: new Exception()) }; disposables.ForEach(scope.RegisterForDisposal); try { // Act scope.Dispose(); // Assert Assert.Fail("Exception was expected to bubble up."); } catch (Exception ex) { Assert.IsTrue(object.ReferenceEquals(lastThrownException, ex)); } }
public void WhenScopeEnds_CalledOnDisposedScope_ThrowsObjectDisposedException() { // Arrange var scope = new Scope(); scope.Dispose(); // Act Action action = () => scope.WhenScopeEnds(() => { }); // Assert AssertThat.Throws<ObjectDisposedException>(action, "Calling WhenScopeEnds should throw an ObjectDisposedException."); }
public void RegisterForDisposal_CalledOnDisposedScope_ThrowsObjectDisposedException() { // Arrange var scope = new Scope(); scope.Dispose(); // Act Action action = () => scope.RegisterForDisposal(new DisposableObject()); // Assert AssertThat.Throws<ObjectDisposedException>(action, "Calling RegisterForDisposal should throw an ObjectDisposedException."); }
public void Dispose_WhenDisposeEndsActionRegisteredDuringDisposal_CallsTheRegisteredDelegate() { // Arrange bool actionCalled = false; var disposable = new DisposableObject(); var scope = new Scope(); var container = new Container(); container.Register<DisposableObject>(() => disposable, new FakeScopedLifestyle(scope)); container.RegisterInitializer<DisposableObject>(instance => { scope.WhenScopeEnds(() => actionCalled = true); }); scope.WhenScopeEnds(() => container.GetInstance<DisposableObject>()); // Act scope.Dispose(); // Assert Assert.IsTrue(actionCalled); }
public void Dispose_ScopedItemResolvedDuringScopeEndAction_GetsDisposed() { // Arrange var disposable = new DisposableObject(); var scope = new Scope(); var container = new Container(); container.Register<DisposableObject>(() => disposable, new FakeScopedLifestyle(scope)); scope.WhenScopeEnds(() => container.GetInstance<DisposableObject>()); // Act scope.Dispose(); // Assert Assert.IsTrue(disposable.IsDisposedOnce); }
public void Dispose_RecursiveResolveTriggeredDuringEndScopeAction_StillDisposesRegisteredDisposables() { // Arrange var scope = new Scope(); var scopedLifestyle = new FakeScopedLifestyle(scope); var container = new Container(); var disposable = new DisposableObject(); scope.RegisterForDisposal(disposable); container.Register<IPlugin>(() => { scope.WhenScopeEnds(() => { container.GetInstance<IPlugin>(); }); return new DisposablePlugin(); }); container.GetInstance<IPlugin>(); try { // Act scope.Dispose(); Assert.Fail("Exception expected."); } catch { // Assert Assert.IsTrue(disposable.IsDisposedOnce, "Even though there was a recursion detected when executing Action delegates, all " + "registered disposables should still get disposed."); } }
public void Dispose() { _scope?.Dispose(); }
public void GetInstance_CalledOnADisposedScope_ThrowsObjectDisposedException() { // Arrange var scope = new Scope(); var scopedLifestyle = new FakeScopedLifestyle(scope); var container = new Container(); container.Register<IPlugin>(() => new DisposablePlugin(), scopedLifestyle); container.GetInstance<IPlugin>(); scope.Dispose(); // Act Action action = () => container.GetInstance<IPlugin>(); // Assert AssertThat.ThrowsWithExceptionMessageContains<ActivationException>( CannotAccessADisposedObjectMessage, action); }
private void OnBeginRequest(object sender, EventArgs eventArgs) { Scope scope = null; try { var tracer = Tracer.Instance; if (!tracer.Settings.IsIntegrationEnabled(IntegrationId)) { // integration disabled return; } var httpContext = (sender as HttpApplication)?.Context; if (httpContext == null) { return; } HttpRequest httpRequest = httpContext.Request; SpanContext propagatedContext = null; var tagsFromHeaders = Enumerable.Empty <KeyValuePair <string, string> >(); var propagator = tracer.Propagator; if (tracer.ActiveScope == null) { try { // extract propagated http headers var headers = httpRequest.Headers.Wrap(); propagatedContext = propagator.Extract(headers); tagsFromHeaders = headers.ExtractHeaderTags(tracer.Settings.HeaderTags); } catch (Exception ex) { Log.Error(ex, "Error extracting propagated HTTP headers."); } } string host = httpRequest.Headers.Get("Host"); string httpMethod = httpRequest.HttpMethod.ToUpperInvariant(); string url = httpRequest.RawUrl.ToLowerInvariant(); var tags = new WebTags(); scope = tracer.StartActiveWithTags(_requestOperationName, propagatedContext, tags: tags); // Leave resourceName blank for now - we'll update it in OnEndRequest scope.Span.DecorateWebServerSpan(resourceName: null, httpMethod, host, url, tags, tagsFromHeaders); tags.SetAnalyticsSampleRate(IntegrationId, tracer.Settings, enabledWithGlobalSetting: true); httpContext.Items[_httpContextScopeKey] = scope; // Decorate the incoming HTTP Request with distributed tracing headers // in case the next processor cannot access the stored Scope // (e.g. WCF being hosted in IIS) propagator.Inject(scope.Span.Context, httpRequest.Headers.Wrap()); } catch (Exception ex) { // Dispose here, as the scope won't be in context items and won't get disposed on request end in that case... scope?.Dispose(); Log.Error(ex, "Datadog ASP.NET HttpModule instrumentation error"); } }
public void GetInstance_ResolvingScopedInstanceWhileDifferentThreadIsVerifying_DoesNotResolveInstanceFromVerificationScope() { // Arrange DisposablePlugin verifiedPlugin = null; DisposablePlugin backgroundResolvedPlugin = null; Task task = null; var container = new Container(); var scope = new Scope(); var lifestyle = new FakeScopedLifestyle(scope); container.Register<IPlugin, DisposablePlugin>(lifestyle); container.RegisterInitializer<DisposablePlugin>(p => { verifiedPlugin = p; // Resolve on a different thread (so not during verification) task = Task.Run(() => { backgroundResolvedPlugin = (DisposablePlugin)container.GetInstance<IPlugin>(); }); Thread.Sleep(150); }); // Act container.Verify(); task.Wait(); // Assert Assert.IsFalse(backgroundResolvedPlugin.IsDisposedOnce, "Since this instance isn't resolved during verification, but within an active scope, " + "The instance should not have been disposed here."); scope.Dispose(); Assert.IsTrue(backgroundResolvedPlugin.IsDisposedOnce, "Now it should have been disposed."); }
public void Dispose() { _metricWrapper?.Dispose(); _sfxScope?.Dispose(); }
public void Dispose() { Scope?.Dispose(); }
public void Dispose_ExceptionThrownDuringDisposalAfterResolvingNewInstance_DoesNotCallAnyNewActions() { // Arrange bool scopeEndActionCalled = false; var scope = new Scope(); var scopedLifestyle = new FakeScopedLifestyle(scope); var container = new Container(); container.Register<IPlugin>(() => new DisposablePlugin()); container.RegisterInitializer<IPlugin>( plugin => scope.WhenScopeEnds(() => scopeEndActionCalled = true)); container.Register<DisposableObject>(() => new DisposableObject(_ => { container.GetInstance<IPlugin>(); throw new Exception("Bang!"); }), scopedLifestyle); try { // Act scope.Dispose(); // Assert Assert.Fail("Exception expected."); } catch { Assert.IsFalse(scopeEndActionCalled, "In case of an exception, no actions will be further executed. This lowers the change " + "the new exceptions are thrown from other actions that cover up the original exception."); } }
public void Dispose_ScopedInstanceResolvedDuringDisposingScope_DisposesThisInstanceLast() { // Arrange var disposedObjects = new List<object>(); var scope = new Scope(); var scopedLifestyle = new FakeScopedLifestyle(scope); var container = new Container(); container.Register<IPlugin>(() => new DisposablePlugin(disposedObjects.Add), scopedLifestyle); container.Register<IDisposable>(() => new DisposableObject(disposedObjects.Add), scopedLifestyle); container.Register<DisposableObject>(() => new DisposableObject(_ => { container.GetInstance<IPlugin>(); }), scopedLifestyle); container.GetInstance<IDisposable>(); container.GetInstance<DisposableObject>(); // Act scope.Dispose(); // Assert AssertThat.IsInstanceOfType(typeof(DisposablePlugin), disposedObjects.Last(), "Since the disposable logger is requested during disposal of the scope, it should be " + "disposed after all other already created services have been disposed. " + "In the given case, disposing DisposableLogger before the IDisposable registration becomes " + "a problem when that registration starts using ILogger in its dispose method as well."); }
public void ShouldThrowExceptionWhenEndingNonCurrentScope() { var container = CreateContainer(); using (container.BeginScope()) { var scope = new Scope(container.ScopeManagerProvider.GetScopeManager(container), null); Assert.Throws<InvalidOperationException>(() => scope.Dispose()); } }
public void Dispose_InstanceResolvedDuringDisposingScopeRegisteringEndAction_CallsThisAction() { // Arrange bool actionCalled = false; var scope = new Scope(); var scopedLifestyle = new FakeScopedLifestyle(scope); var container = new Container(); container.Register<DisposableObject>(() => new DisposableObject(_ => { container.GetInstance<IPlugin>(); }), scopedLifestyle); container.Register<IPlugin>(() => { scope.WhenScopeEnds(() => actionCalled = true); return new DisposablePlugin(); }, Lifestyle.Transient); container.GetInstance<DisposableObject>(); // Act scope.Dispose(); // Assert Assert.IsTrue(actionCalled); }
public void Dispose_ExceptionThrownDuringDisposalAfterResolvingNewInstance_DisposesThatInstance() { // Arrange bool newlyResolvedInstanceDisposed = false; var scope = new Scope(); var scopedLifestyle = new FakeScopedLifestyle(scope); var container = new Container(); container.Register<IPlugin>( () => new DisposablePlugin(disposing: _ => newlyResolvedInstanceDisposed = true), scopedLifestyle); container.Register<DisposableObject>(() => new DisposableObject(disposing: _ => { container.GetInstance<IPlugin>(); throw new Exception("Bang!"); }), scopedLifestyle); container.GetInstance<DisposableObject>(); try { // Act scope.Dispose(); // Assert Assert.Fail("Exception expected."); } catch { Assert.IsTrue(newlyResolvedInstanceDisposed); } }
public void Dispose_RegisteredActionAndRegisteredDisposableObject_CallsActionFirst() { // Arrange int actionCount = 0; int disposeCount = 0; var scope = new Scope(); scope.RegisterForDisposal(new DisposableObject(_ => { Assert.AreEqual(2, actionCount); disposeCount++; })); scope.WhenScopeEnds(() => { Assert.AreEqual(0, disposeCount); actionCount++; }); scope.WhenScopeEnds(() => { Assert.AreEqual(0, disposeCount); actionCount++; }); scope.RegisterForDisposal(new DisposableObject(_ => { Assert.AreEqual(2, actionCount); disposeCount++; })); // Act scope.Dispose(); // Assert Assert.AreEqual(2, actionCount); Assert.AreEqual(2, disposeCount); }
public static bool EndInvokeAction( object asyncControllerActionInvoker, object asyncResult, int opCode, int mdToken, long moduleVersionPtr) { if (asyncControllerActionInvoker == null) { throw new ArgumentNullException(nameof(asyncControllerActionInvoker)); } Scope scope = null; var httpContext = HttpContext.Current; try { scope = httpContext?.Items[HttpContextKey] as Scope; } catch (Exception ex) { Log.Error(ex, "Error instrumenting method {0}", $"{AsyncActionInvokerTypeName}.EndInvokeAction()"); } Func <object, object, bool> instrumentedMethod; try { var asyncActionInvokerType = asyncControllerActionInvoker.GetInstrumentedInterface(AsyncActionInvokerTypeName); instrumentedMethod = MethodBuilder <Func <object, object, bool> > .Start(moduleVersionPtr, mdToken, opCode, nameof(EndInvokeAction)) .WithConcreteType(asyncActionInvokerType) .WithParameters(asyncResult) .WithNamespaceAndNameFilters(ClrNames.Bool, ClrNames.IAsyncResult) .Build(); } catch (Exception ex) { Log.ErrorRetrievingMethod( exception: ex, moduleVersionPointer: moduleVersionPtr, mdToken: mdToken, opCode: opCode, instrumentedType: AsyncActionInvokerTypeName, methodName: nameof(EndInvokeAction), instanceType: asyncControllerActionInvoker.GetType().AssemblyQualifiedName); throw; } try { // call the original method, inspecting (but not catching) any unhandled exceptions return(instrumentedMethod(asyncControllerActionInvoker, asyncResult)); } catch (Exception ex) { scope?.Span.SetException(ex); throw; } finally { scope?.Dispose(); } }