/// <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."); } }
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"); }
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(); } }
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); }
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()); } }
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"); }
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"); }
/// <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 } }