private static void HookOrProcessResult(HttpWebRequest request) { IAsyncResult writeAsyncContext = writeAResultAccessor(request); if (writeAsyncContext == null || !(asyncCallbackAccessor(writeAsyncContext)?.Target is AsyncCallbackWrapper writeAsyncContextCallback)) { // If we already hooked into the read result during ProcessRequest or we hooked up after the fact already we don't need to do anything here. return; } // If we got here it means the user called [Begin]GetRequestStream[Async] and we have to hook the read result after the fact. IAsyncResult readAsyncContext = readAResultAccessor(request); if (readAsyncContext == null) { // We're still trying to establish the connection (no read has started). return; } // Clear our saved callback so we know not to process again. asyncCallbackModifier(writeAsyncContext, null); if (endCalledAccessor.Invoke(readAsyncContext) || readAsyncContext.CompletedSynchronously) { // We need to process the result directly because the read callback has already fired. Force a copy because response has likely already been disposed. ProcessResult(readAsyncContext, null, writeAsyncContextCallback.Activity, resultAccessor(readAsyncContext), true); return; } // Hook into the result callback if it hasn't already fired. AsyncCallbackWrapper callback = new AsyncCallbackWrapper(writeAsyncContextCallback.Request, writeAsyncContextCallback.Activity, asyncCallbackAccessor(readAsyncContext)); asyncCallbackModifier(readAsyncContext, callback.AsyncCallback); }
private void RaiseRequestEvent(HttpWebRequest request) { if (this.IsRequestInstrumented(request)) { // This request was instrumented by previous RaiseRequestEvent, such is the case with redirect responses where the same request is sent again. return; } if (this.IsEnabled(ActivityName, request)) { // We don't call StartActivity here because it will fire into user code before the headers are added. var activity = new Activity(ActivityName); activity.Start(); IAsyncResult asyncContext = readAResultAccessor(request); if (asyncContext != null) { // Flow here is for [Begin]GetResponse[Async] without a prior call to [Begin]GetRequestStream[Async]. AsyncCallbackWrapper callback = new AsyncCallbackWrapper(request, activity, asyncCallbackAccessor(asyncContext)); asyncCallbackModifier(asyncContext, callback.AsyncCallback); } else { // Flow here is for [Begin]GetRequestStream[Async]. asyncContext = writeAResultAccessor(request); AsyncCallbackWrapper callback = new AsyncCallbackWrapper(request, activity, asyncCallbackAccessor(asyncContext)); asyncCallbackModifier(asyncContext, callback.AsyncCallback); } InstrumentRequest(request, activity); // Only send start event to users who subscribed for it, but start activity anyway if (this.IsEnabled(RequestStartName)) { this.Write(activity.OperationName + ".Start", new { Request = request }); } } }
private static void ProcessRequest(HttpWebRequest request) { if (!WebRequestActivitySource.HasListeners() || IsRequestInstrumented(request)) { // No subscribers to the ActivitySource or this request was instrumented by previous // ProcessRequest, such is the case with redirect responses where the same request is sent again. return; } var activity = WebRequestActivitySource.StartActivity(ActivityName, ActivityKind.Client); if (activity == null) { // There is a listener but it decided not to sample the current request. return; } IAsyncResult asyncContext = writeAResultAccessor(request); if (asyncContext != null) { // Flow here is for [Begin]GetRequestStream[Async]. AsyncCallbackWrapper callback = new AsyncCallbackWrapper(request, activity, asyncCallbackAccessor(asyncContext)); asyncCallbackModifier(asyncContext, callback.AsyncCallback); } else { // Flow here is for [Begin]GetResponse[Async] without a prior call to [Begin]GetRequestStream[Async]. asyncContext = readAResultAccessor(request); AsyncCallbackWrapper callback = new AsyncCallbackWrapper(request, activity, asyncCallbackAccessor(asyncContext)); asyncCallbackModifier(asyncContext, callback.AsyncCallback); } AddRequestTagsAndInstrumentRequest(request, activity); }