-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make BuildUri
public
#2026
Comments
Depends on #2025 |
I think this is used for logging. What about remembering the URL in a public property after the operation? |
For me the BuildUri makes a lot of things e.g. putting query parameters to the uri string. So it is not done by a simple remembering the URL. I have solved the issues with a custom tracking So the example / pseudo codes logs and tracks the requests with times: public class LoggingClientHandler : DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var stopwatch = new Stopwatch();
_logger.LogDebug("Starting request to '{Request}' using method {Method}", request.RequestUri, request.Method);
var response = await base.SendAsync(request, cancellationToken);
_logger.LogDebug("Request to '{Request}' using method {Method} done in {Duration}", request.RequestUri, request.Method, stopwatch.Elapsed);
return response;
}
} The real implementation also checks the response status codes and so on. For me there is no longer a requirement to access the BuildUri method because I have implemented an alternative (maybe a more better/resilent way) to track the requests |
Looking at this, I am trying to understand what it means. Your solution for logging is great, I agree that it's a much better to do things like diagnostics and tracing. Btw, there's an open issue to support call tracing, and I think using a delegated handler would also be how I'd implement that. But, it doesn't cover "a lot of things" that you mentioned, is there anything else you needed this method for? |
"A lot of things" was a little bit excessive. I have used BuildUri to create the correct uri include query parameters. That's it. With the built uri include query parameters I have logged and tracked the times. With all the information I was able to check the performance. For example I can identify network issues when the client metric is much slower than the server endpoint metrics. For external ressources I have not developed by myself it was the only thing to measure performance client side. To find out that the DelegatedHandlers exists helped me to clean up und makes it much easier and cleaner. |
@nesc58 , could you give me more info about your LoggingClientHandler class? I'm not seeing the AddHandler method, and I'm not sure how to implement your solution. Best |
I found the hook in |
I think all the diagnostic use cases would be solved by this #1669 You'd basically add a listener to the named |
If BuildUri is not going to be restored, what is the recommended method to determine the full request URI from the clinet/request objects? We too were using BuildUri for logging/exception messaging |
This worked for me: public class LoggingClientHandler : DelegatingHandler
{
readonly Action<string>? _Logger = null;
public LoggingClientHandler(HttpMessageHandler innerHandler, Action<string>? logger = null) : base(innerHandler)
{
_Logger = logger;
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
_Logger?.Invoke($"{request.Method} {request.RequestUri}");
var response = await base.SendAsync(request, cancellationToken);
return response;
}
} and then var options = new RestClientOptions("...url...")
{
ConfigureMessageHandler = (inner_handler) => new LoggingClientHandler(inner_handler, (s)=>Debug.Print(s)),
};
RestClient client = new(options, configureSerialization: cfg => cfg.UseNewtonsoftJson()); I hope it helps |
I would love having an extension or similar. |
Yeah @nsulikowski is right. public class LoggingDelegatingHandler : DelegatingHandler
{
private readonly ILogger _logger;
public LoggingDelegatingHandler(ILogger logger, HttpMessageHandler innerHandler) : base(innerHandler)
{
_logger = logger;
}
#if NET6_0_OR_GREATER
protected override HttpResponseMessage Send(HttpRequestMessage request, CancellationToken cancellationToken)
{
var stopwatch = Stopwatch.StartNew();
_logger.LogDebug("Starting request to '{Request}' using method {Method}", request.RequestUri, request.Method);
var response = base.Send(request, cancellationToken);
_logger.LogDebug("Request to '{Request}' using method {Method} done in {Duration}", request.RequestUri, request.Method, stopwatch.Elapsed);
return response;
}
#endif
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var stopwatch = Stopwatch.StartNew();
_logger.LogDebug("Starting request to '{Request}' using method {Method}", request.RequestUri, request.Method);
var response = await base.SendAsync(request, cancellationToken).ConfigureAwait(false);
_logger.LogDebug("Request to '{Request}' using method {Method} done in {Duration}", request.RequestUri, request.Method, stopwatch.Elapsed);
return response;
}
} And here is the initialization: var options = new RestClientOptions
{
ConfigureMessageHandler = handler => new LoggingDelegatingHandler(_logger, handler);
}; Like this i am able to add multiple delegating handlers by nesting them: var options = new RestClientOptions(/*....*/)
{
/* all other options */
ConfigureMessageHandler = handler =>
{
var withLogging = new LoggingDelegatingHandler(_logger, handler);
var withMetrics = new AppMetricsDelegatingHandler(_logger, _metricsStore, withLogging);
// and so on
return withMetrics;
};
}; |
I am waiting for more feedback about other possible use cases for public |
What's your usage pattern? Chained delegating handlers seems to be a neat solution. I can also work on the activity source, which is an alternative way to receive diagnostics. |
Is this fixed? This is currently the only constraint preventing us from upgrading to newer versions. |
@pedoc fixed what? I asked for feedback about usage of |
Like the previous version, make BuildUrl public and allow external access. We currently mainly use it for logging scenarios. Unlike the alternatives given above, we hope to simply record the request address and related information directly at the call site, instead of using callbacks or more complicated solutions. |
I am not sure why is it easier as you need to configure the logging handler once when you set up the client, and it will log everything. When you log explicitly in every place where you actually make the call, it's very easy to forget to add the logging line. Using a logging handler is very reliable, and when the RestClient will be instrumented with activity source it would be even easier, as it won't require any configuration of the client. Instead, you'd just add a logging listener to the activity source and it will log all the calls made by any RestClient instance in the system. |
As I wrote before, You expect |
What I can do now is to make |
Hey! |
Signature generation, its important to get an exact match so nicer to ensure we use the same method for url generation in signature and for the request made |
Those who are interested in |
From the previous discussion:
The only property not including in the interface is
DefaultParameters
.If this will not be a part of the interface or of the IRestClientOptions it could be optional:
If this method will not be accessible in future it is bad for me but solvable.
Originally posted by @nesc58 in #1976 (comment)
The text was updated successfully, but these errors were encountered: