Beispiel #1
0
        /// <summary>
        /// Processes Begin request by starting subsegment.
        /// </summary>
        private void ProcessBeginRequest(IExecutionContext executionContext)
        {
            var    request = executionContext.RequestContext.Request;
            Entity entity  = null;

            try
            {
                entity = _recorder.GetEntity();
            }
            catch (EntityNotAvailableException e)
            {
                _recorder.TraceContext.HandleEntityMissing(_recorder, e, "Cannot get entity while processing AWS SDK request");
            }

            var serviceName = RemoveAmazonPrefixFromServiceName(request.ServiceName);

            _recorder.BeginSubsegment(AWSXRaySDKUtils.FormatServiceName(serviceName));
            _recorder.SetNamespace("aws");

            entity = entity == null ? null : _recorder.GetEntity();

            if (TraceHeader.TryParse(entity, out TraceHeader traceHeader))
            {
                request.Headers[TraceHeader.HeaderKey] = traceHeader.ToString();
            }
            else
            {
                _logger.DebugFormat("Failed to inject trace header to AWS SDK request as the segment can't be converted to TraceHeader.");
            }
        }
        private static void ProcessRequest(Uri uri, string method, Action <string> addHeaderAction)
        {
            if (AWSXRayRecorder.Instance.IsTracingDisabled())
            {
                _logger.DebugFormat("Tracing is disabled. Not starting a subsegment on HTTP request.");
                return;
            }

            var recorder = AWSXRayRecorder.Instance;

            recorder.BeginSubsegment(uri.Host);
            recorder.SetNamespace("remote");

            var requestInformation = new Dictionary <string, object>
            {
                ["url"]    = uri.AbsoluteUri,
                ["method"] = method
            };

            recorder.AddHttpInformation("request", requestInformation);

            try
            {
                if (TraceHeader.TryParse(recorder.GetEntity(), out var header))
                {
                    addHeaderAction(header.ToString());
                }
            }
            catch (EntityNotAvailableException e)
            {
                recorder.TraceContext.HandleEntityMissing(recorder, e, "Failed to get entity since it is not available in trace context while processing http request.");
            }
        }
Beispiel #3
0
        protected override WebRequest GetWebRequest(Uri address)
        {
            var request = base.GetWebRequest(address);

            if (request != null)
            {
                request.Timeout = this.Timeout;
            }

            if (AwsUtilityMethods.IsRunningOnAWS)
            {
                AWSXRayRecorder.Instance.BeginSubsegment(request.RequestUri.Host);
                AWSXRayRecorder.Instance.SetNamespace("remote");
                Dictionary <string, object> requestInformation = new Dictionary <string, object>();
                requestInformation["url"]    = request.RequestUri.AbsoluteUri;
                requestInformation["method"] = request.Method;
                AWSXRayRecorder.Instance.AddHttpInformation("request", requestInformation);

                if (TraceHeader.TryParse(TraceContext.GetEntity(), out TraceHeader header))
                {
                    request.Headers.Add("X-Amzn-Trace-Id", header.ToString());
                }
            }

            return(request);
        }
        public void TestTryParseNullString()
        {
            TraceHeader header;
            string      nullString = null;

            Assert.IsFalse(TraceHeader.TryParse(nullString, out header));
        }
        public void TestTrParseWithInvalidTraceId()
        {
            string      input = "Root=1-5759e988";
            TraceHeader header;

            Assert.IsFalse(TraceHeader.TryParse(input, out header));
            Assert.IsNull(header);
        }
        public void TestTryParseSampleRequested()
        {
            string      input = "Root=1-5759e988-bd862e3fe1be46a994272793; Sampled=?";
            TraceHeader header;

            Assert.IsTrue(TraceHeader.TryParse(input, out header));
            Assert.AreEqual(SampleDecision.Requested, header.Sampled);
        }
        public void TestTryParseWithInvalidParentId()
        {
            string      input = "Root=1-5759e988-bd862e3fe1be46a994272793; Parent=215748";
            TraceHeader header;

            Assert.IsFalse(TraceHeader.TryParse(input, out header));
            Assert.IsNull(header);
        }
        /// <summary>
        /// Processes HTTP request.
        /// </summary>
        private void ProcessHTTPRequest(HttpContext context)
        {
            HttpRequest request      = context.Request;
            string      headerString = null;

            if (request.Headers.TryGetValue(TraceHeader.HeaderKey, out StringValues headerValue))
            {
                if (headerValue.ToArray().Length >= 1)
                {
                    headerString = headerValue.ToArray()[0];
                }
            }

            // Trace header doesn't exist, which means this is the root node. Create a new traceId and inject the trace header.
            if (!TraceHeader.TryParse(headerString, out TraceHeader traceHeader))
            {
                _logger.DebugFormat("Trace header doesn't exist or not valid : ({0}). Injecting a new one.", headerString);
                traceHeader = new TraceHeader
                {
                    RootTraceId = TraceId.NewId(),
                    ParentId    = null,
                    Sampled     = SampleDecision.Unknown
                };
            }

            bool isSampleDecisionRequested = traceHeader.Sampled == SampleDecision.Requested;

            // Make sample decision
            if (traceHeader.Sampled == SampleDecision.Unknown || traceHeader.Sampled == SampleDecision.Requested)
            {
                string serviceName = request.Host.Host;
                string url         = request.Path;
                string method      = request.Method;
                traceHeader.Sampled = _recorder.SamplingStrategy.Sample(serviceName, url, method);
            }

            if (AWSXRayRecorder.Instance.IsLambda())
            {
                _recorder.BeginSubsegment(SegmentNamingStrategy.GetSegmentName(request));
            }
            else
            {
                _recorder.BeginSegment(SegmentNamingStrategy.GetSegmentName(request), traceHeader.RootTraceId, traceHeader.ParentId, traceHeader.Sampled);
            }

            if (!AWSXRayRecorder.Instance.IsTracingDisabled())
            {
                var requestAttributes = new Dictionary <string, object>();
                PopulateRequestAttributes(request, requestAttributes);
                _recorder.AddHttpInformation("request", requestAttributes);
            }

            if (isSampleDecisionRequested)
            {
                context.Response.Headers.Add(TraceHeader.HeaderKey, traceHeader.ToString()); // Its recommended not to modify response header after _next.Invoke() call
            }
        }
        public void TestTryParseInvalidString()
        {
            string[] invalidStrings = new string[] { "asdfhdk=fidksldfj", "asdfhdkfidksldfj", ";", ";=", string.Empty };

            foreach (string s in invalidStrings)
            {
                TraceHeader header;
                Assert.IsFalse(TraceHeader.TryParse(s, out header));
            }
        }
        public void TestTryParseWithOnlyRootTraceId()
        {
            string      input = "Root=1-5759e988-bd862e3fe1be46a994272793;";
            TraceHeader header;

            Assert.IsTrue(TraceHeader.TryParse(input, out header));
            Assert.AreEqual("1-5759e988-bd862e3fe1be46a994272793", header.RootTraceId);
            Assert.IsNull(header.ParentId);
            Assert.AreEqual(SampleDecision.Unknown, header.Sampled);
        }
        public void TestTryParseWithRootParentSampled()
        {
            string      input = "Root=1-5759e988-bd862e3fe1be46a994272793; Parent=defdfd9912dc5a56; Sampled=1";
            TraceHeader header;

            Assert.IsTrue(TraceHeader.TryParse(input, out header));

            Assert.AreEqual("1-5759e988-bd862e3fe1be46a994272793", header.RootTraceId);
            Assert.AreEqual("defdfd9912dc5a56", header.ParentId);
            Assert.AreEqual(SampleDecision.Sampled, header.Sampled);
        }
        /// <summary>
        /// Processes Begin request by starting subsegment.
        /// </summary>
        private void ProcessBeginRequest(IExecutionContext executionContext)
        {
            var request = executionContext.RequestContext.Request;

            if (TraceHeader.TryParse(_recorder.GetEntity(), out TraceHeader traceHeader))
            {
                request.Headers[TraceHeader.HeaderKey] = traceHeader.ToString();
            }
            else
            {
                _logger.DebugFormat("Failed to inject trace header to AWS SDK request as the segment can't be converted to TraceHeader.");
            }

            _recorder.BeginSubsegment(RemoveAmazonPrefixFromServiceName(request.ServiceName));
            _recorder.SetNamespace("aws");
        }
Beispiel #13
0
        private static void ProcessRequest(WebRequest request)
        {
            if (!AWSXRayRecorder.Instance.IsTracingDisabled())
            {
                AWSXRayRecorder.Instance.BeginSubsegment(request.RequestUri.Host);
                AWSXRayRecorder.Instance.SetNamespace("remote");

                Dictionary <string, object> requestInformation = new Dictionary <string, object>();
                requestInformation["url"]    = request.RequestUri.AbsoluteUri;
                requestInformation["method"] = request.Method;
                AWSXRayRecorder.Instance.AddHttpInformation("request", requestInformation);
            }

            if (TraceHeader.TryParse(TraceContext.GetEntity(), out TraceHeader header))
            {
                request.Headers.Add(TraceHeader.HeaderKey, header.ToString());
            }
        }
        public void TestTryParseSubsegment()
        {
            using (var recorder = new AWSXRayRecorder())
            {
                recorder.BeginSegment("TraceHeaderTest", TraceId);
                recorder.BeginSubsegment("subjob");
                var subsegment = TraceContext.GetEntity();

                TraceHeader header;
                Assert.IsTrue(TraceHeader.TryParse(subsegment, out header));

                Assert.AreEqual(TraceId, header.RootTraceId);
                Assert.AreEqual(subsegment.Id, header.ParentId);
                Assert.AreEqual(SampleDecision.Sampled, header.Sampled);

                recorder.EndSubsegment();
                recorder.EndSegment();
            }
        }
Beispiel #15
0
        private void ProcessBeginRequest(IExecutionContext executionContext)
        {
            var    request = executionContext.RequestContext.Request;
            Entity entity  = null;

            try
            {
                entity = _recorder.GetEntity();
            }
            catch (EntityNotAvailableException e)
            {
                _recorder.TraceContext.HandleEntityMissing(_recorder, e, "Cannot get entity while processing AWS SDK request");
            }

            _recorder.BeginSubsegment(RemoveAmazonPrefixFromServiceName(request.ServiceName));
            _recorder.SetNamespace("aws");

            entity = entity == null ? null : _recorder.GetEntity();

            if (TraceHeader.TryParse(entity, out var traceHeader))
            {
                request.Headers[TraceHeader.HeaderKey] = traceHeader.ToString();

                if (request.Parameters.Any(p => p.Value == "AWSTraceHeader"))
                {
                    return;
                }

                var index = request
                            .Parameters
                            .Where(x => x.Key.StartsWith("MessageSystemAttribute"))
                            .Select(x => int.TryParse(x.Value.Split('.')[1], out var idx) ? idx : 0)
                            .Union(new[] { 0 })
                            .Max() + 1;

                request.Parameters.Add("MessageSystemAttribute" + "." + index + "." + "Name",
                                       StringUtils.FromString("AWSTraceHeader"));
                request.Parameters.Add("MessageSystemAttribute" + "." + index + "." + "Value.DataType",
                                       StringUtils.FromString("String"));
                request.Parameters.Add("MessageSystemAttribute" + "." + index + "." + "Value" + "." + "StringValue",
                                       StringUtils.FromString(traceHeader.ToString()));
            }
        }
        /// <summary>
        /// Returns instance of <see cref="TraceHeader"/> class from given <see cref="HttpContext"/> object.
        /// </summary>
        private static TraceHeader GetTraceHeader(HttpContext context)
        {
            var    request      = context.Request;
            string headerString = request.Headers.Get(TraceHeader.HeaderKey);

            // Trace header doesn't exist, which means this is the root node. Create a new traceId and inject the trace header.
            if (!TraceHeader.TryParse(headerString, out TraceHeader traceHeader))
            {
                _logger.DebugFormat("Trace header doesn't exist or not valid : ({0}). Injecting a new one.", headerString);
                traceHeader = new TraceHeader
                {
                    RootTraceId = TraceId.NewId(),
                    ParentId    = null,
                    Sampled     = SampleDecision.Unknown
                };
            }

            return(traceHeader);
        }
Beispiel #17
0
 private void ProcessRequest(HttpRequestMessage request)
 {
     if (!AWSXRayRecorder.Instance.IsTracingDisabled())
     {
         AWSXRayRecorder.Instance.BeginSubsegment(!string.IsNullOrEmpty(_overrideSubSegmentNameFunc?.Invoke(request)) ? _overrideSubSegmentNameFunc(request) : request.RequestUri.Host);
         AWSXRayRecorder.Instance.SetNamespace(Namespace ?? "remote");
         var dictionary =
             new Dictionary <string, object>
         {
             ["url"]    = request.RequestUri.AbsoluteUri,
             ["method"] = request.Method.Method
         };
         AWSXRayRecorder.Instance.AddHttpInformation(nameof(request), dictionary);
         if (!TraceHeader.TryParse(TraceContext.GetEntity(), out var header))
         {
             return;
         }
         request.Headers.Add("X-Amzn-Trace-Id", header.ToString());
     }
 }
Beispiel #18
0
        private void BeforeRequestEventHandler(object sender, RequestEventArgs e)
        {
            var args = e as WebServiceRequestEventArgs;

            if (args == null)
            {
                _logger.DebugFormat("Failed to handle BeforeRequestEvent, because e can't be converted to WebServiceRequestEventArgs.");
                return;
            }
            if (TraceHeader.TryParse(_recorder.GetEntity(), out TraceHeader traceHeader))
            {
                args.Headers[TraceHeader.HeaderKey] = traceHeader.ToString();
            }
            else
            {
                _logger.DebugFormat("Failed to inject trace header to AWS SDK request as the segment can't be converted to TraceHeader.");
            }
            _recorder.BeginSubsegment(RemoveAmazonPrefixFromServiceName(args.ServiceName));
            _recorder.SetNamespace("aws");
        }
Beispiel #19
0
        private static void ProcessRequest(Uri uri, string method, Action <string> addHeaderAction)
        {
            if (!AWSXRayRecorder.Instance.IsTracingDisabled())
            {
                AWSXRayRecorder.Instance.BeginSubsegment(uri.Host);
                AWSXRayRecorder.Instance.SetNamespace("remote");

                var requestInformation = new Dictionary <string, object>
                {
                    ["url"]    = uri.AbsoluteUri,
                    ["method"] = method
                };
                AWSXRayRecorder.Instance.AddHttpInformation("request", requestInformation);
            }

            if (TraceHeader.TryParse(AWSXRayRecorder.Instance.TraceContext.GetEntity(), out var header))
            {
                addHeaderAction(header.ToString());
            }
        }
 private static void GetSamplingDetails(
     IAWSXRayRecorder xRayRecorder, string serviceName, string traceHeader, out string traceId, out SamplingResponse samplingResponse,
     out string parentId)
 {
     if (TraceHeader.TryParse(traceHeader, out TraceHeader header))
     {
         traceId          = header.RootTraceId;
         samplingResponse = new SamplingResponse {
             SampleDecision = header.Sampled
         };
         parentId = header.ParentId;
     }
     else
     {
         traceId          = TraceId.NewId();
         samplingResponse = xRayRecorder.SamplingStrategy.ShouldTrace(new SamplingInput {
             ServiceName = serviceName
         });
         parentId = null;
     }
 }
        /// <summary>
        /// Processes Begin request by starting subsegment.
        /// </summary>
        private void ProcessBeginRequest(IExecutionContext executionContext)
        {
            if (AWSXRayRecorder.Instance.IsTracingDisabled())
            {
                _logger.DebugFormat("X-Ray tracing is disabled, do not handle AWSSDK request.");
                return;
            }

            var request = executionContext.RequestContext.Request;

            if (TraceHeader.TryParse(TraceContext.GetEntity(), out TraceHeader traceHeader))
            {
                request.Headers[TraceHeader.HeaderKey] = traceHeader.ToString();
            }
            else
            {
                _logger.DebugFormat("Failed to inject trace header to AWS SDK request as the segment can't be converted to TraceHeader.");
            }

            _recorder.BeginSubsegment(RemoveAmazonPrefixFromServiceName(request.ServiceName));
            _recorder.SetNamespace("aws");
        }
Beispiel #22
0
 /// <inheritdoc/>
 public string?GetIdFromHeader(string?header)
 {
     return((!TraceHeader.TryParse(header, out var parsedHeader) || string.IsNullOrEmpty(parsedHeader.RootTraceId))
         ? null
         : parsedHeader.RootTraceId);
 }
        /// <summary>
        /// Sends an HTTP request to the inner handler to send to the server as an asynchronous
        /// operation.
        /// </summary>
        /// <param name="request">The HTTP request message to send to the server.</param>
        /// <param name="cancellationToken">A cancellation token to cancel operation.</param>
        /// <returns>Returns System.Threading.Tasks.Task. The task object representing the asynchronous operation.</returns>
        protected async override Task <HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
        {
            string headerSring = null;

            if (request.Headers.TryGetValues(TraceHeader.HeaderKey, out IEnumerable <string> headerValue))
            {
                headerSring = headerValue.First();
            }

            // If Trace header doesn't exist, which means this is the root node. Create a new traceId and inject the trace header.
            if (!TraceHeader.TryParse(headerSring, out TraceHeader traceHeader))
            {
                _logger.DebugFormat("Trace header doesn't exist or not valid. Injecting a new one. existing header = {0}", headerSring);
                traceHeader = new TraceHeader
                {
                    RootTraceId = TraceId.NewId(),
                    ParentId    = null,
                    Sampled     = SampleDecision.Unknown
                };
            }

            bool isSampleDecisionRequested = traceHeader.Sampled == SampleDecision.Requested;

            // Make sample decision
            if (traceHeader.Sampled == SampleDecision.Unknown || traceHeader.Sampled == SampleDecision.Requested)
            {
                traceHeader.Sampled = _recorder.SamplingStrategy.Sample(request);
            }

            _recorder.BeginSegment(SegmentNamingStrategy.GetSegmentName(request), traceHeader.RootTraceId, traceHeader.ParentId, traceHeader.Sampled);

            if (!AppSettings.IsXRayTracingDisabled)
            {
                var requestAttributes = new Dictionary <string, object>();
                requestAttributes["url"]    = request.RequestUri.AbsoluteUri;
                requestAttributes["method"] = request.Method.Method;
                string xForwardedFor = GetXForwardedFor(request);
                if (xForwardedFor == null)
                {
                    requestAttributes["client_ip"] = GetClientIpAddress(request);
                }
                else
                {
                    requestAttributes["client_ip"]       = xForwardedFor;
                    requestAttributes["x_forwarded_for"] = true;
                }

                requestAttributes["user_agent"] = request.Headers.UserAgent.ToString();
                _recorder.AddHttpInformation("request", requestAttributes);
            }

            var response = await base.SendAsync(request, cancellationToken);

            if (!AppSettings.IsXRayTracingDisabled)
            {
                var responseAttributes = new Dictionary <string, object>();
                int statusCode         = (int)response.StatusCode;
                if (statusCode >= 400 && statusCode <= 499)
                {
                    _recorder.MarkError();
                    if (statusCode == 429)
                    {
                        _recorder.MarkThrottle();
                    }
                }
                else if (statusCode >= 500 && statusCode <= 599)
                {
                    _recorder.MarkFault();
                }

                responseAttributes["status"] = statusCode;

                if (response.Content != null && response.Content.Headers.ContentLength != null)
                {
                    responseAttributes["content_length"] = response.Content.Headers.ContentLength;
                }

                _recorder.AddHttpInformation("response", responseAttributes);
            }

            _recorder.EndSegment();

            // If the sample decision is requested, added the trace header to response
            if (isSampleDecisionRequested)
            {
                response.Headers.Add(TraceHeader.HeaderKey, traceHeader.ToString());
            }

            return(response);
        }
        /// <summary>
        /// Process http request.
        /// </summary>
        internal static void ProcessRequest(HttpContext httpContext)
        {
            HttpRequest request      = httpContext.Request;
            string      headerString = null;

            if (request.Headers.TryGetValue(TraceHeader.HeaderKey, out StringValues headerValue))
            {
                if (headerValue.Count >= 1)
                {
                    headerString = headerValue[0];
                }
            }

            if (!TraceHeader.TryParse(headerString, out TraceHeader traceHeader))
            {
                _logger.DebugFormat("Trace header doesn't exist or not valid : ({0}). Injecting a new one.", headerString);
                traceHeader = new TraceHeader
                {
                    RootTraceId = TraceId.NewId(),
                    ParentId    = null,
                    Sampled     = SampleDecision.Unknown
                };
            }

            var  segmentName = SegmentNamingStrategy.GetSegmentName(request);
            bool isSampleDecisionRequested = traceHeader.Sampled == SampleDecision.Requested;

            string ruleName = null;

            // Make sample decision
            if (traceHeader.Sampled == SampleDecision.Unknown || traceHeader.Sampled == SampleDecision.Requested)
            {
                string           host           = request.Host.Host;
                string           url            = request.Path;
                string           method         = request.Method;
                SamplingInput    samplingInput  = new SamplingInput(host, url, method, segmentName, _recorder.Origin);
                SamplingResponse sampleResponse = _recorder.SamplingStrategy.ShouldTrace(samplingInput);
                traceHeader.Sampled = sampleResponse.SampleDecision;
                ruleName            = sampleResponse.RuleName;
            }

            if (AWSXRayRecorder.IsLambda())
            {
                _recorder.BeginSubsegment(segmentName);
            }
            else
            {
                SamplingResponse samplingResponse = new SamplingResponse(ruleName, traceHeader.Sampled); // get final ruleName and SampleDecision
                _recorder.BeginSegment(SegmentNamingStrategy.GetSegmentName(request), traceHeader.RootTraceId, traceHeader.ParentId, samplingResponse);
            }

            if (!AWSXRayRecorder.Instance.IsTracingDisabled())
            {
                var requestAttributes = PopulateRequestAttributes(request);
                _recorder.AddHttpInformation("request", requestAttributes);
            }

            // Mark the segment as auto-instrumented
            AgentUtil.AddAutoInstrumentationMark();

            if (isSampleDecisionRequested)
            {
                httpContext.Response.Headers.Add(TraceHeader.HeaderKey, traceHeader.ToString()); // Its recommended not to modify response header after _next.Invoke() call
            }
        }