#c# #amazon-web-services #restsharp #aws-xray
#c# #amazon-веб-сервисы #restsharp #aws-xray
Вопрос:
В настоящее время у нас есть внутренняя библиотека, которую мы используем для выполнения многих наших HTTP-вызовов, которая использует RestSharp, а не HttpClient для выполнения всех наших запросов к нижестоящим службам. Возможно ли включить трассировку рентгеновских лучей в AWS без перезаписи этой библиотеки, чтобы вместо этого использовать HttpClient? Цель состоит в том, чтобы получить ту же функциональность, которая была бы описана здесь (при использовании HttpClient): https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-dotnet-httpclients.html
Комментарии:
1. Что вы в конечном итоге сделали, чтобы решить свою проблему?
Ответ №1:
Библиотека RestSharp представляет собой отдельный HTTP-клиент, который X-Ray SDK для .NET в настоящее время не поддерживает. Я не знаком с RestSharp, но я полагаю, что он использует HttpClient под капотом, поскольку это встроенная библиотека для HTTP-вызовов в .NET. Итак, если бы вы могли каким-то образом заменить базовый HttpClient, используемый библиотекой RestSharp, на инструментальную версию HttpClient, это позволило бы выполнять трассировку рентгеновских лучей, но я не уверен, возможна ли такая замена.
X-Ray SDK для .NET имеет открытый исходный код, и мы с радостью примем запросы на извлечение, если вы хотите написать модуль для поддержки X-Ray RestSharphttps://github.com/aws/aws-xray-sdk-dotnet
Комментарии:
1. Правильно, RestSharp использует
HttpWebRequest
, который, в свою очередь, используетHttpClient
. На самом деле это довольно легко настроитьHttpClient
ненавязчивым образом с помощью диагностических прослушивателей, как это делается в OpenTracing github.com/opentracing-contrib/csharp-netcore/blob/master/src /…2. Не могли бы вы немного рассказать о том, что потребуется с технической точки зрения, чтобы добавить поддержку RestSharp? Вы упоминали о написании модуля? Есть ли у вас образец модуля, на который кто-нибудь может ссылаться при рассмотрении вопроса о его создании? Можете ли вы дать несколько советов?
3. Каковы необходимые и достаточные шаги для обновления dotnet xray sdk, чтобы он поддерживал RestSharp? Не могли бы вы, пожалуйста, дать несколько указаний? Я полагаю, вы упоминали что-то о «модуле». Что такое модуль в этом отношении? Является ли это специфичной концепцией xray sdk, о которой я могу где-нибудь узнать больше?
4. @AlexeyZimarev, я не верю, что клиенты библиотеки RestSharp обновляют экземпляр HttpClient непосредственно в своем вызывающем коде. Я полагаю, что ваша ссылка предназначена для всех, кто обновляет экземпляр HttpClient. Когда кто-то использует преимущества RestSharp, они, скорее всего, будут обновлять только экземпляры RestSharp.
5. @jbooker это правда, но любой инструментарий с
System.Diagnostics
, использующий activities, может быть легко расширен извне. Как только вы создадите действие перед отправкой запроса с помощью RestSharp, оно будет распространено с помощьюHttpClient
. Кроме того, это имеет мало общего сHttpClient
экземпляром, поскольку трассировка выполняется по каждому запросу.
Ответ №2:
Вот как я в конечном итоге реализовал это — практически невозможно перехватить что-либо в RestSharp, поэтому я выбрал обратный подход, разбив и изменив расширение «GetResponseTraced»:
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 amp;amp; num <= 499)
{
AWSXRayRecorder.Instance.MarkError();
if (num == 429)
AWSXRayRecorder.Instance.MarkThrottle();
}
else if (num >= 500 amp;amp; num <= 599)
AWSXRayRecorder.Instance.MarkFault();
dictionary["content_length"] = (object)contentLength;
AWSXRayRecorder.Instance.AddHttpInformation("response", (object)dictionary);
}
}
}