public void RewriteTraceContext(SQSEvent.SQSMessage sqsMessage, ILambdaContext lambdaContext)
        {
            var traceHeader           = TraceHeader.FromString(sqsMessage.Attributes["AWSTraceHeader"]);
            var lambdaSegmentParentId = traceHeader.ParentId;
            var lambdaSegmentId       = Entity.GenerateId();

            traceHeader.ParentId = lambdaSegmentId;

            Environment.SetEnvironmentVariable(AWSXRayRecorder.LambdaTraceHeaderKey, traceHeader.ToString());

            _lambdaSegment = new Segment(lambdaContext.FunctionName, traceHeader.RootTraceId)
            {
                Id       = lambdaSegmentId,
                ParentId = lambdaSegmentParentId,
                Sampled  = traceHeader.Sampled,
                Origin   = "AWS::Lambda::Function",
                Aws      =
                {
                    { "account_id",     lambdaContext.InvokedFunctionArn.Split(":")[4] },
                    { "function_arn",   lambdaContext.InvokedFunctionArn               },
                    { "resource_names", new List <string> {
                          lambdaContext.FunctionName
                      } }
                }
            };

            _lambdaSegment.SetStartTime(_startTime);
        }
        public void TestTryParseNullString()
        {
            TraceHeader header;
            string      nullString = null;

            Assert.IsFalse(TraceHeader.TryParse(nullString, out header));
        }
Esempio n. 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);
        }
Esempio n. 4
0
        /// <summary>
        /// Processes HTTP response.
        /// </summary>
        private static void ProcessHTTPResponse(Object sender, EventArgs e)
        {
            var context  = ((HttpApplication)sender).Context;
            var response = context.Response;

            if (!AWSXRayRecorder.Instance.IsTracingDisabled() && response != null)
            {
                Dictionary <string, object> responseAttributes = new Dictionary <string, object>();
                ProcessResponseAttributes(response, responseAttributes);
                _recorder.AddHttpInformation("response", responseAttributes);
            }

            Exception exc = context.Error; // Record exception, if any

            if (exc != null)
            {
                _recorder.AddException(exc);
            }

            TraceHeader traceHeader = GetTraceHeader(context);
            bool        isSampleDecisionRequested = traceHeader.Sampled == SampleDecision.Requested;

            if (traceHeader.Sampled == SampleDecision.Unknown || traceHeader.Sampled == SampleDecision.Requested)
            {
                SetSamplingDecision(traceHeader); // extracts sampling decision from the available segment
            }

            _recorder.EndSegment();
            // if the sample decision is requested, add the trace header to response
            if (isSampleDecisionRequested)
            {
                response.Headers.Add(TraceHeader.HeaderKey, traceHeader.ToString());
            }
        }
Esempio n. 5
0
 public static TraceHeader GetTraceHeader(this Message message)
 {
     return
         (message.Attributes.TryGetValue(Constants.TraceHeader, out var value)
             ? TraceHeader.FromString(value)
             : null);
 }
        /// <summary>
        /// Processes HTTP request.
        /// </summary>
        private static void ProcessHTTPRequest(Object sender, EventArgs e)
        {
            var context = ((HttpApplication)sender).Context;

            if (context.Items.Contains(XRayEntity))
            {
                return; // Do not override segment for the current request
            }

            var         request     = context.Request;
            TraceHeader traceHeader = GetTraceHeader(context);

            // Make sample decision
            if (traceHeader.Sampled == SampleDecision.Unknown || traceHeader.Sampled == SampleDecision.Requested)
            {
                SetSamplingDecision(request, traceHeader);
            }

            var timestamp = context.Timestamp.ToUniversalTime().ToUnixTimeSeconds(); // Gets initial timestamp of current HTTP Request

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

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

            context.Items.Add(XRayEntity, Core.Internal.Utils.TraceContext.GetEntity());
        }
        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.");
            }
        }
Esempio n. 8
0
 private static void LogTimes(TraceHeader th)
 {
     Console.Write("{0}", th.OccurredAt);
     if (th.Duration == TimeSpan.Zero)
     {
         Console.Write("  |               ");
     }
     else
     {
         if (th.Duration > threshold)
         {
             if (th.NextHeader != null &&
                 th.NextHeader.TraceEntry.IsUITriggered)
             {
                 Console.Write("@>");
             }
             else
             {
                 Console.Write("=>");
             }
         }
         else
         {
             Console.Write("  ");
         }
         Console.Write("{0:dd\\.hh\\:mm\\:ss\\.fff} ", th.Duration);
     }
 }
Esempio n. 9
0
        /// <summary>
        /// Processes HTTP request.
        /// </summary>
        private static void ProcessHTTPRequest(Object sender, EventArgs e)
        {
            var context = ((HttpApplication)sender).Context;

            string ruleName = null;

            var         request     = context.Request;
            TraceHeader traceHeader = GetTraceHeader(context);

            var segmentName = GetSegmentNamingStrategy().GetSegmentName(request);

            // Make sample decision
            if (traceHeader.Sampled == SampleDecision.Unknown || traceHeader.Sampled == SampleDecision.Requested)
            {
                SamplingResponse response = MakeSamplingDecision(request, traceHeader, segmentName);
                ruleName = response.RuleName;
            }

            var timestamp = context.Timestamp.ToUniversalTime();                                     // Gets initial timestamp of current HTTP Request

            SamplingResponse samplingResponse = new SamplingResponse(ruleName, traceHeader.Sampled); // get final ruleName and SampleDecision

            _recorder.BeginSegment(segmentName, traceHeader.RootTraceId, traceHeader.ParentId, samplingResponse, timestamp);

            if (!AWSXRayRecorder.Instance.IsTracingDisabled())
            {
                Dictionary <string, object> requestAttributes = new Dictionary <string, object>();
                ProcessRequestAttributes(request, requestAttributes);
                _recorder.AddHttpInformation("request", requestAttributes);
            }
        }
Esempio n. 10
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 SetSamplingDecision(HttpRequest request, TraceHeader traceHeader)
        {
            string serviceName = request.Headers.Get("Host");
            string url         = request.Url.AbsolutePath;
            string method      = request.HttpMethod;

            traceHeader.Sampled = _recorder.SamplingStrategy.Sample(serviceName, url, method);
        }
        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 TestTrParseWithInvalidTraceId()
        {
            string      input = "Root=1-5759e988";
            TraceHeader header;

            Assert.IsFalse(TraceHeader.TryParse(input, out header));
            Assert.IsNull(header);
        }
        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);
        }
Esempio n. 18
0
        private static void ProcessTraceHeader(TraceHeader traceHeader, MutableObject traceMutable)
        {
            MutableObject header = new MutableObject();

            header.Add("Binary ID", (int)traceHeader.BinaryId);
            header.Add("Magic", (int)traceHeader.Magic);
            header.Add("Version", (int)traceHeader.Version);
            header.Add("Flags", (int)traceHeader.Flags);

            traceMutable.Add("Header", header);
        }
Esempio n. 19
0
        private static SamplingResponse MakeSamplingDecision(HttpRequest request, TraceHeader traceHeader, string name)
        {
            string           host           = request.Headers.Get("Host");
            string           url            = request.Url.AbsolutePath;
            string           method         = request.HttpMethod;
            SamplingInput    samplingInput  = new SamplingInput(host, url, method, name, _recorder.Origin);
            SamplingResponse sampleResponse = _recorder.SamplingStrategy.ShouldTrace(samplingInput);

            traceHeader.Sampled = sampleResponse.SampleDecision;
            return(sampleResponse);
        }
        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);
        }
        public void TestToStringUnknown()
        {
            var header = new TraceHeader();

            header.RootTraceId = "1-5759e988-bd862e3fe1be46a994272793";
            header.ParentId    = "defdfd9912dc5a56";
            header.Sampled     = SampleDecision.Unknown;

            var expected = "Root=1-5759e988-bd862e3fe1be46a994272793; Parent=defdfd9912dc5a56";

            Assert.AreEqual(expected, header.ToString());
        }
Esempio n. 22
0
        public async Task <TraceHeader> SaveTraceHeaderAsync(TraceHeader header)
        {
            using (IDbConnection connection = new NpgsqlConnection(GetConnectionString()))
            {
                var sql = @"INSERT INTO traceheader(filedataid, tracename, blocksize, tracedate, vunit, hresolution, hoffset, hunit)
                            VALUES(@FileDataId, @TraceName, @BlockSize, @TraceDate, @VUnit, @HResolution, @HOffSet, @HUnit)
                            RETURNING traceheaderid;";

                header.TraceHeaderId = await connection.ExecuteScalarAsync <int>(sql, header);

                return(header);
            }
        }
        private static void SetSamplingDecision(TraceHeader traceHeader)
        {
            try
            {
                Segment segment = (Segment)AWSXRayRecorder.Instance.GetEntity();
                traceHeader.Sampled = segment.Sampled;
            }

            catch (InvalidCastException e)
            {
                _logger.Error(new EntityNotAvailableException("Failed to cast the entity to Segment.", e), "Failed to  get the segment from trace context for setting sampling decision in the response.");
            }
        }
        /// <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");
        }
Esempio n. 25
0
        private static void SetSamplingDecision(TraceHeader traceHeader)
        {
            try
            {
                Segment segment = (Segment)AWSXRayRecorder.Instance.GetEntity();
                traceHeader.Sampled = segment.Sampled;
            }

            catch (InvalidCastException e)
            {
                _logger.Error(new EntityNotAvailableException("Failed to cast the entity to Segment.", e), "Failed to  get the segment from trace context for setting sampling decision in the response.");
            }

            catch (EntityNotAvailableException e)
            {
                AWSXRayRecorder.Instance.TraceContext.HandleEntityMissing(AWSXRayRecorder.Instance, e, "Failed to get entity since it is not available in trace context while processing ASPNET request.");
            }
        }
Esempio n. 26
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());
            }
        }
Esempio n. 27
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()));
            }
        }
Esempio n. 28
0
        static void Main(string[] args)
        {
            var random = new Random();
            // make sure Zipkin with Scribe client is working
            //var collector = new HttpCollector(new Uri("http://localhost:9411/"));
            var collector = new KafkaCollector(KafkaSettings.Default);
            var traceId   = new TraceHeader(traceId: (ulong)random.Next(), spanId: (ulong)random.Next());
            var span      = new Span(traceId, new IPEndPoint(IPAddress.Loopback, 9000), "test-service");

            span.Record(Annotations.ClientSend(DateTime.UtcNow));
            Thread.Sleep(100);
            span.Record(Annotations.ServerReceive(DateTime.UtcNow));
            Thread.Sleep(100);
            span.Record(Annotations.ServerSend(DateTime.UtcNow));
            Thread.Sleep(100);
            span.Record(Annotations.ClientReceive(DateTime.UtcNow));

            collector.CollectAsync(span).Wait();
        }
        /// <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);
        }
        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();
            }
        }