Reputation: 2108
We currently have an internal library that we're using to make a lot of our HTTP calls that uses RestSharp rather that the HttpClient to make all of our requests to downstream services. Is it possible to enable x-ray tracing in AWS without re-writing that library to instead use HttpClient? The goal is to get the same functionality that would be outlined here (when using HttpClient): https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-dotnet-httpclients.html
Upvotes: 0
Views: 542
Reputation: 1
This is how I ended up implementing it - near impossible to intercept anything in RestSharp, so I took the reverse approach of breaking down and modifying the "GetResponseTraced" extension:
public static class RestClientXrayExtensions
{
public static IRestResponse ExecuteTraced(this IRestClient client, IRestRequest request)
{
return client.ExecuteTraced(request, () => client.Execute(request));
}
public static IRestResponse<T> ExecuteTraced<T>(this IRestClient client, IRestRequest request)
where T : new()
{
return client.ExecuteTraced(request, () => client.Execute<T>(request));
}
public static IRestResponse ExecuteAsGetTraced(this IRestClient client, IRestRequest request, string httpMethod)
{
return client.ExecuteTraced(request, () => client.ExecuteAsGet(request, httpMethod));
}
private static TResponse ExecuteTraced<TRequest,TResponse>(this IRestClient client, TRequest request, Func<TResponse> execute)
where TRequest : IRestRequest
where TResponse : IRestResponse
{
ProcessRequest(client.BuildUri(request), request.Method.ToString(), header => request.AddHeader("X-Amzn-Trace-Id", header));
try
{
var response = execute();
ProcessResponse(response.StatusCode, response.ContentLength);
return response;
}
catch (Exception ex)
{
AWSXRayRecorder.Instance.AddException(ex);
throw;
}
finally
{
AWSXRayRecorder.Instance.EndSubsegment(new DateTime?());
}
}
private static void ProcessRequest(Uri uri, string method, Action<string> addHeaderAction)
{
if (!AWSXRayRecorder.Instance.IsTracingDisabled())
{
AWSXRayRecorder instance = AWSXRayRecorder.Instance;
instance.BeginSubsegment(uri.Host, new DateTime?());
instance.SetNamespace("remote");
Dictionary<string, object> dictionary = new Dictionary<string, object>()
{
["url"] = (object)uri.AbsoluteUri,
[nameof(method)] = (object)method
};
instance.AddHttpInformation("request", (object)dictionary);
try
{
TraceHeader header;
if (!TraceHeader.TryParse(instance.GetEntity(), out header))
return;
addHeaderAction(header.ToString());
}
catch (EntityNotAvailableException ex)
{
instance.TraceContext.HandleEntityMissing((IAWSXRayRecorder)instance, (Exception)ex, "Failed to get entity since it is not available in trace context while processing http request.");
}
}
}
private static void ProcessResponse(HttpStatusCode httpStatusCode, long? contentLength)
{
if (!AWSXRayRecorder.Instance.IsTracingDisabled())
{
int num = (int)httpStatusCode;
Dictionary<string, object> dictionary = new Dictionary<string, object>()
{
["status"] = (object)num
};
if (num >= 400 && num <= 499)
{
AWSXRayRecorder.Instance.MarkError();
if (num == 429)
AWSXRayRecorder.Instance.MarkThrottle();
}
else if (num >= 500 && num <= 599)
AWSXRayRecorder.Instance.MarkFault();
dictionary["content_length"] = (object)contentLength;
AWSXRayRecorder.Instance.AddHttpInformation("response", (object)dictionary);
}
}
}
Upvotes: 0
Reputation: 273
The RestSharp library is a separate HTTP client which the X-Ray SDK for .NET does not support at this time. I'm not familiar with RestSharp, but I believe it uses HttpClient under the hood as that is the native library for HTTP calls in .NET. So if you could somehow replace the underlying HttpClient used by the RestSharp library with an instrumented version of HttpClient, that would enable X-Ray tracing, but I'm not sure if such a replacement is possible.
The X-Ray SDK for .NET is open sourced, and we're happy to take pull requests if you'd like to write a module for X-Ray RestSharp support https://github.com/aws/aws-xray-sdk-dotnet
Upvotes: 0