public void OperationContextIsSetForNonRequestTelemetry()
        {
            var source = new TestableOperationCorrelationTelemetryInitializer(new Dictionary <string, string>
            {
                ["Request-Id"]          = "|guid.1",
                ["Correlation-Context"] = "k1=v1,k2=v2,k1=v3"
            });

            // simulate OnBegin behavior:
            // create telemetry and start activity for children
            var requestTelemetry = source.FakeContext.CreateRequestTelemetryPrivate();

            // lost Acitivity / call context
            ActivityHelpers.CleanOperationContext();

            var exceptionTelemetry = new ExceptionTelemetry();

            source.Initialize(exceptionTelemetry);

            Assert.AreEqual(requestTelemetry.Context.Operation.Id, exceptionTelemetry.Context.Operation.Id);
            Assert.AreEqual(requestTelemetry.Id, exceptionTelemetry.Context.Operation.ParentId);

            Assert.AreEqual(2, exceptionTelemetry.Context.Properties.Count);

            // undefined behavior for duplicates
            Assert.IsTrue(exceptionTelemetry.Context.Properties["k1"] == "v3" || exceptionTelemetry.Context.Properties["k1"] == "v1");
            Assert.AreEqual("v2", exceptionTelemetry.Context.Properties["k2"]);
        }
Exemplo n.º 2
0
        public void TelemetryCreatedWithinRequestScopeIsRequestChildWhenActivityIsLost()
        {
            var context = HttpModuleHelper.GetFakeHttpContext(new Dictionary <string, string>
            {
                ["Request-Id"]          = "|guid1.1",
                ["Correlation-Context"] = "k=v"
            });

            var config = this.CreateDefaultConfig(context);
            var module = this.RequestTrackingTelemetryModuleFactory(config);

            module.OnBeginRequest(context);

            // simulate losing call context by cleaning up activity
            ActivityHelpers.CleanOperationContext();

            var telemetryClient = new TelemetryClient(config);

            var trace = new TraceTelemetry();

            telemetryClient.TrackTrace(trace);
            var requestTelemetry = context.GetRequestTelemetry();

            Assert.Equal(requestTelemetry.Context.Operation.Id, trace.Context.Operation.Id);
            Assert.Equal(requestTelemetry.Id, trace.Context.Operation.ParentId);
            Assert.Equal("v", trace.Context.Properties["k"]);
        }
Exemplo n.º 3
0
        public void OnPreHandlerTelemetryCreatedWithinRequestScopeIsRequestChild()
        {
            var context = HttpModuleHelper.GetFakeHttpContext(new Dictionary <string, string>
            {
                ["Request-Id"]          = "|guid1.1",
                ["Correlation-Context"] = "k=v"
            });

            var config = this.CreateDefaultConfig(context);
            var module = this.RequestTrackingTelemetryModuleFactory(config);

            module.OnBeginRequest(context);

            // simulate losing call context by cleaning up activity
            ActivityHelpers.CleanOperationContext();

            // CallContext was lost after OnBegin, so OnPreRequestHandlerExecute will set it
            module.OnPreRequestHandlerExecute(context);

            // if OnPreRequestHandlerExecute set a CallContext, child telemetry will be properly filled
            var telemetryClient = new TelemetryClient(config);

            var trace = new TraceTelemetry();

            telemetryClient.TrackTrace(trace);
            var requestTelemetry = context.GetRequestTelemetry();

            Assert.Equal(requestTelemetry.Context.Operation.Id, trace.Context.Operation.Id);
            Assert.Equal(requestTelemetry.Id, trace.Context.Operation.ParentId);
            Assert.Equal("v", trace.Context.Properties["k"]);
        }
Exemplo n.º 4
0
        public void Cleanup()
        {
#if NET452
            while (Activity.Current != null)
            {
                Activity.Current.Stop();
            }
#else
            ActivityHelpers.CleanOperationContext();
#endif
        }
Exemplo n.º 5
0
        public void Cleanup()
        {
            while (this.sentTelemetry.TryDequeue(out _))
            {
            }

#if NET45
            while (Activity.Current != null)
            {
                Activity.Current.Stop();
            }
#else
            ActivityHelpers.CleanOperationContext();
#endif
        }
        public void OperationContextIsNotUpdatedIfOperationIdIsSet()
        {
            var source = new TestableOperationCorrelationTelemetryInitializer(new Dictionary <string, string>
            {
                ["Request-Id"]          = "|guid.1",
                ["Correaltion-Context"] = "k1=v1"
            });

            // create telemetry and immediately clean call context/activity
            source.FakeContext.CreateRequestTelemetryPrivate();
            ActivityHelpers.CleanOperationContext();

            var exceptionTelemetry = new ExceptionTelemetry();

            exceptionTelemetry.Context.Operation.Id = "guid";
            source.Initialize(exceptionTelemetry);

            Assert.IsNull(exceptionTelemetry.Context.Operation.ParentId);

            Assert.AreEqual(0, exceptionTelemetry.Context.Properties.Count);
        }
        /// <summary>
        /// Implements on end callback of http module.
        /// </summary>
        public void OnEndRequest(HttpContext context)
        {
            if (this.telemetryClient == null)
            {
                if (!this.initializationErrorReported)
                {
                    this.initializationErrorReported = true;
                    WebEventSource.Log.InitializeHasNotBeenCalledOnModuleYetError();
                }
                else
                {
                    WebEventSource.Log.InitializeHasNotBeenCalledOnModuleYetVerbose();
                }

                return;
            }

            if (!this.NeedProcessRequest(context))
            {
                return;
            }

#if NET40
            // we store Activity/Call context to initialize child telemtery within the scope of this request,
            // so it's time to stop it
            ActivityHelpers.CleanOperationContext();
#endif
            var requestTelemetry = context.ReadOrCreateRequestTelemetryPrivate();
            requestTelemetry.Stop();

            var success = true;
            if (string.IsNullOrEmpty(requestTelemetry.ResponseCode))
            {
                var statusCode = context.Response.StatusCode;
                requestTelemetry.ResponseCode = statusCode.ToString(CultureInfo.InvariantCulture);

                if (statusCode >= 400 && statusCode != 401)
                {
                    success = false;
                }
            }

            if (!requestTelemetry.Success.HasValue)
            {
                requestTelemetry.Success = success;
            }

            if (requestTelemetry.Url == null)
            {
                requestTelemetry.Url = context.Request.UnvalidatedGetUrl();
            }

            if (string.IsNullOrEmpty(requestTelemetry.Context.InstrumentationKey))
            {
                // Instrumentation key is probably empty, because the context has not yet had a chance to associate the requestTelemetry to the telemetry client yet.
                // and get they instrumentation key from all possible sources in the process. Let's do that now.
                this.telemetryClient.Initialize(requestTelemetry);
            }

            if (string.IsNullOrEmpty(requestTelemetry.Source) && context.Request.Headers != null)
            {
                string telemetrySource = string.Empty;
                string sourceAppId     = null;

                try
                {
                    sourceAppId = context.Request.UnvalidatedGetHeaders().GetNameValueHeaderValue(RequestResponseHeaders.RequestContextHeader, RequestResponseHeaders.RequestContextCorrelationSourceKey);
                }
                catch (Exception ex)
                {
                    AppMapCorrelationEventSource.Log.GetCrossComponentCorrelationHeaderFailed(ex.ToInvariantString());
                }

                bool correlationIdLookupHelperInitialized = this.TryInitializeCorrelationHelperIfNotInitialized();

                string currentComponentAppId = string.Empty;
                bool   foundMyAppId          = false;
                if (!string.IsNullOrEmpty(requestTelemetry.Context.InstrumentationKey) && correlationIdLookupHelperInitialized)
                {
                    foundMyAppId = this.correlationIdLookupHelper.TryGetXComponentCorrelationId(requestTelemetry.Context.InstrumentationKey, out currentComponentAppId);
                }

                // If the source header is present on the incoming request,
                // and it is an external component (not the same ikey as the one used by the current component),
                // then populate the source field.
                if (!string.IsNullOrEmpty(sourceAppId) &&
                    foundMyAppId &&
                    sourceAppId != currentComponentAppId)
                {
                    telemetrySource = sourceAppId;
                }

                string sourceRoleName = null;

                try
                {
                    sourceRoleName = context.Request.UnvalidatedGetHeaders().GetNameValueHeaderValue(RequestResponseHeaders.RequestContextHeader, RequestResponseHeaders.RequestContextSourceRoleNameKey);
                }
                catch (Exception ex)
                {
                    AppMapCorrelationEventSource.Log.GetComponentRoleNameHeaderFailed(ex.ToInvariantString());
                }

                if (!string.IsNullOrEmpty(sourceRoleName))
                {
                    if (string.IsNullOrEmpty(telemetrySource))
                    {
                        telemetrySource = "roleName:" + sourceRoleName;
                    }
                    else
                    {
                        telemetrySource += " | roleName:" + sourceRoleName;
                    }
                }

                requestTelemetry.Source = telemetrySource;
            }

            this.telemetryClient.TrackRequest(requestTelemetry);
        }