Пример #1
0
        public void TestElasticBeanstalkPlugin()
        {
            var mockEBPlugin = new Mock <IPlugin>();
            IDictionary <string, object> fakeEBContext = new Dictionary <string, object>();

            fakeEBContext.Add("deployment_id", "1");
            fakeEBContext.Add("environment_id", "1");
            fakeEBContext.Add("environment_name", "test");
            fakeEBContext.Add("version_label", "v0");
            mockEBPlugin.Setup(x => x.Origin).Returns("AWS::ElasticBeanstalk::Environment");
            mockEBPlugin.Setup(x => x.ServiceName).Returns("elastic_beanstalk");
            mockEBPlugin.Setup(x => x.TryGetRuntimeContext(out fakeEBContext)).Returns(true);

            var recorder = new AWSXRayRecorderBuilder().WithPlugin(mockEBPlugin.Object).Build();
            var traceId  = TraceId.NewId();

            recorder.BeginSegment(GetType().Name, traceId);
            Thread.Sleep(100);
            recorder.EndSegment();
#if NET45
            var response = BatchGetTraces(traceId);
#else
            var response = BatchGetTracesAsync(traceId).Result;
#endif
            Assert.IsTrue(response.Traces.Count > 0);

            var segmentJsonData = JsonMapper.ToObject(response.Traces[0].Segments[0].Document);
            Assert.AreEqual("AWS::ElasticBeanstalk::Environment", (string)segmentJsonData["origin"]);
            var ebJsonData = segmentJsonData["aws"]["elastic_beanstalk"];
            Assert.AreEqual("1", (string)ebJsonData["deployment_id"]);
            Assert.AreEqual("1", (string)ebJsonData["environment_id"]);
            Assert.AreEqual("test", (string)ebJsonData["environment_name"]);
            Assert.AreEqual("v0", (string)ebJsonData["version_label"]);
        }
Пример #2
0
        public void TestEC2Plugin()
        {
            var mockEC2Plugin = new Mock <IPlugin>();
            IDictionary <string, object> fakeEC2Context = new Dictionary <string, object>();

            fakeEC2Context.Add("instance_id", "i-0ae00afcb550c1164");
            fakeEC2Context.Add("availability_zone", "us-east-1d");
            fakeEC2Context.Add("instance_size", "c4.large");
            fakeEC2Context.Add("ami_id", "ami-a32a7eb4");
            mockEC2Plugin.Setup(x => x.Origin).Returns("AWS::EC2::Instance");
            mockEC2Plugin.Setup(x => x.ServiceName).Returns("ec2");
            mockEC2Plugin.Setup(x => x.TryGetRuntimeContext(out fakeEC2Context)).Returns(true);

            var recorder = new AWSXRayRecorderBuilder().WithPlugin(mockEC2Plugin.Object).Build();
            var traceId  = TraceId.NewId();

            recorder.BeginSegment(GetType().Name, traceId);
            Thread.Sleep(100);
            recorder.EndSegment();

#if NET45
            var response = BatchGetTraces(traceId);
#else
            var response = BatchGetTracesAsync(traceId).Result;
#endif
            Assert.IsTrue(response.Traces.Count > 0);

            var segmentJsonData = JsonMapper.ToObject(response.Traces[0].Segments[0].Document);
            Assert.AreEqual("AWS::EC2::Instance", (string)segmentJsonData["origin"]);
            var ec2JsonData = segmentJsonData["aws"]["ec2"];
            Assert.AreEqual("i-0ae00afcb550c1164", (string)ec2JsonData["instance_id"]);
            Assert.AreEqual("us-east-1d", (string)ec2JsonData["availability_zone"]);
            Assert.AreEqual("c4.large", (string)ec2JsonData["instance_size"]);
            Assert.AreEqual("ami-a32a7eb4", (string)ec2JsonData["ami_id"]);
        }
Пример #3
0
        public void TestECSPlugin()
        {
            var mockECSPlugin = new Mock <IPlugin>();
            IDictionary <string, object> fakeECSContext = new Dictionary <string, object>();

            fakeECSContext.Add("container", "localhost");
            mockECSPlugin.Setup(x => x.Origin).Returns("AWS::ECS::Container");
            mockECSPlugin.Setup(x => x.ServiceName).Returns("ecs");
            mockECSPlugin.Setup(x => x.TryGetRuntimeContext(out fakeECSContext)).Returns(true);

            var recorder = new AWSXRayRecorderBuilder().WithPlugin(mockECSPlugin.Object).Build();
            var traceId  = TraceId.NewId();

            recorder.BeginSegment(GetType().Name, traceId);
            Thread.Sleep(100);
            recorder.EndSegment();
#if NET45
            var response = BatchGetTraces(traceId);
#else
            var response = BatchGetTracesAsync(traceId).Result;
#endif
            Assert.IsTrue(response.Traces.Count > 0);

            var segmentJsonData = JsonMapper.ToObject(response.Traces[0].Segments[0].Document);
            Assert.AreEqual("AWS::ECS::Container", (string)segmentJsonData["origin"]);
            var ecsJsonData = segmentJsonData["aws"]["ecs"];
            Assert.AreEqual("localhost", (string)ecsJsonData["container"]);
        }
Пример #4
0
        public static void ContinueFrom(this AWSXRayRecorder recorder, string serviceName, Message message)
        {
            var traceHeader = message?.GetTraceHeader() ?? new TraceHeader
            {
                RootTraceId = TraceId.NewId(),
                ParentId    = null,
                Sampled     = SampleDecision.Unknown
            };

            string ruleName = null;

            if (traceHeader.Sampled == SampleDecision.Unknown || traceHeader.Sampled == SampleDecision.Requested)
            {
                var samplingInput  = new SamplingInput(serviceName);
                var sampleResponse = recorder.SamplingStrategy.ShouldTrace(samplingInput);
                traceHeader.Sampled = sampleResponse.SampleDecision;
                ruleName            = sampleResponse.RuleName;
            }

            var samplingResponse = new SamplingResponse(ruleName, traceHeader.Sampled);

            recorder
            .BeginSegment
            (
                serviceName,
                traceHeader.RootTraceId,
                traceHeader.ParentId,
                samplingResponse
            );
        }
        /// <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
            }
        }
        /// <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);
        }
 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;
     }
 }
Пример #8
0
        public void TestMultipleSubsegments()
        {
            var traceId = TraceId.NewId();

            Recorder.BeginSegment(GetType().Name, traceId);

            for (int i = 0; i < 3; i++)
            {
                Recorder.BeginSubsegment("downstream" + i);
                Recorder.EndSubsegment();
            }

            Dictionary <string, string> subsegmentNames = new Dictionary <string, string>();

            TraceContext.GetEntity().Subsegments.ForEach(x => subsegmentNames[x.Id] = x.Name);

            Recorder.EndSegment();
#if NET45
            var response = BatchGetTraces(traceId);
#else
            var response = BatchGetTracesAsync(traceId).Result;
#endif
            Assert.IsTrue(response.Traces.Count > 0);

            var segmentJsonData = JsonMapper.ToObject(response.Traces[0].Segments[0].Document);

            var subsegments = segmentJsonData["subsegments"];
            Assert.IsNotNull(subsegments);
            Assert.AreEqual(3, subsegments.Count);

            for (int i = 0; i < 3; i++)
            {
                Assert.AreEqual((string)subsegments[i]["name"], (string)subsegmentNames[(string)subsegments[i]["id"]]);
                subsegmentNames.Remove((string)subsegments[i]["id"]);
            }

            Assert.AreEqual(0, subsegmentNames.Count);
        }
Пример #9
0
        public void TestMinimalSegment()
        {
            var traceId = TraceId.NewId();

            Recorder.BeginSegment(GetType().Name, traceId);
            var segment = TraceContext.GetEntity();

            Thread.Sleep(100);
            Recorder.EndSegment();
#if NET45
            var response = BatchGetTraces(traceId);
#else
            var response = BatchGetTracesAsync(traceId).Result;
#endif
            Assert.IsTrue(response.Traces.Count > 0);

            var segmentJsonData = JsonMapper.ToObject(response.Traces[0].Segments[0].Document);
            Assert.AreEqual(traceId, (string)segmentJsonData["trace_id"]);
            Assert.AreEqual(segment.Id, (string)segmentJsonData["id"]);
            Assert.AreEqual(segment.Name, (string)segmentJsonData["name"]);
            Assert.AreEqual(segment.StartTime.ToString("F5"), ((double)segmentJsonData["start_time"]).ToString("F5"));
            Assert.AreEqual(segment.EndTime.ToString("F5"), ((double)segmentJsonData["end_time"]).ToString("F5"));
        }
Пример #10
0
        private void Seed(AppUserContext appUserContext, OutboxContext outboxContext, ILogger <Startup> logger)
        {
            // XRAY - EFCore - AsyncLocal Problems
            string traceId = TraceId.NewId();

            AWSXRayRecorder.Instance.BeginSegment("DB Migration", traceId);
            try
            {
                logger.LogInformation("Initializing AppUserContext Database Migration.");
                appUserContext.Database.Migrate();
                logger.LogInformation("Finishing AppUserContext Database Migration...");
                logger.LogInformation("Initializing OutboxContext Database Migration.");
                outboxContext.Database.Migrate();
                logger.LogInformation("Finishing OutboxContext Database Migration...");
            }
            catch (Exception)
            {
                AWSXRayRecorder.Instance.AddException(e);
            }
            finally
            {
                AWSXRayRecorder.Instance.EndSegment();
            }
        }
        /// <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
            }
        }
Пример #13
0
 /// <inheritdoc/>
 public string CreateId()
 {
     return(TraceId.NewId());
 }