Skip to content
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

fix: list found httpclient implementations and output selected one #4936

Merged
merged 1 commit into from
Apr 4, 2023

Conversation

metacosm
Copy link
Collaborator

@metacosm metacosm commented Mar 1, 2023

Description

Fixes #4935

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • Feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change
  • Chore (non-breaking change which doesn't affect codebase;
    test, version modification, documentation, etc.)

Checklist

  • Code contributed by me aligns with current project license: Apache 2.0
  • I Added CHANGELOG entry regarding this change
  • I have implemented unit tests to cover my changes
  • I have added/updated the javadocs and other documentation accordingly
  • No new bugs, code smells, etc. in SonarCloud report
  • I tested my code in Kubernetes
  • I tested my code in OpenShift

return factory;
}

private static HttpClient.Factory getFactory(ServiceLoader<HttpClient.Factory> loader) {
HttpClient.Factory factory = null;
List<String> detectedFactories = new ArrayList<>(7);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

7? That's aspirational.

@@ -73,7 +74,6 @@ public void before(BasicBuilder builder, HttpRequest request, RequestTags tags)
private static final Pattern IPV4_PATTERN = Pattern.compile(
"(http://|https://)?(?<ipAddressOrSubnet>(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])(\\/([1-2]\\d|3[0-2]|\\d))?)(\\D+|$)");
private static final Pattern INVALID_HOST_PATTERN = Pattern.compile("[^\\da-zA-Z.\\-/:]+");
private static final AtomicBoolean MULTIPLE_HTTP_CLIENT_WARNING_LOGGED = new AtomicBoolean();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could get a little chatty in some extreme case - the user has multiple http clients in the classpath, relies upon the default logic to create one of the client types, but specifies the other one programmatically.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't they all get picked up by the ServiceLoader at once, though?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or is it a matter that the method might be called several times, thus leading to the warning being output several times? If that's the case, this actually raises the question of whether or not we should record the chosen factory "once and for all" to avoid going through the resolution process every time a new client is created? Another potential issue is whether or not we want to support creating clients with implicitly different http clients?

Copy link
Contributor

@shawkins shawkins Mar 2, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or is it a matter that the method might be called several times, thus leading to the warning being output several times?

Yes, every client KubernetesClient creation that does not specify a HttpClient.Factory makes this call.

If that's the case, this actually raises the question of whether or not we should record the chosen factory "once and for all" to avoid going through the resolution process every time a new client is created?

Possibly. Some people would cache the ServiceLoader, its iterator will provide new instances should they be found later. However I would not want this to be static as the current HttpClientUtils is. There are several other usages of ServiceLoader in fabric8 that are created for each use. The only one that is not I believe is the KubernetesDeserializer because the resulting mapping is held statically.

Another potential issue is whether or not we want to support creating clients with implicitly different http clients?

That seems fine if your circumstances allow for that - you'd have to be doing something odd like dynamically installing new services or changing the priority of an existing one for the selection to change.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have to admit that's a little concerning because I was under the (maybe misguided) impression that creating a client was a rather fast operation. If we do http client resolution each time now, i.e. class path scanning, it might not be as much. If installing new services dynamically is not considered a core use case, it should be fine to always use the same resolved instance all the time (after the initial lookup).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(maybe misguided) impression that creating a client was a rather fast operation

It should be especially in comparison to how long it should be used - any remote round trip will end up being orders of magnitude greater than the time to create the client.

If we do http client resolution each time now, i.e. class path scanning, it might not be as much

The ServiceToURLProvider has the same approach and you could make the same case about places that make repeated calls to loadClass.

If installing new services dynamically is not considered a core use case, it should be fine to always use the same resolved instance all the time (after the initial lookup)

It's mostly a question of where to put it - if you want to refactor so that it's held on the KuberenetesClientBuilder in some fashion that would be fine, but I would avoid doing anything statically.

@shawkins shawkins self-requested a review March 6, 2023 12:14
Copy link
Contributor

@shawkins shawkins left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Taking a step back, this should be fine for almost all usage. There will not be repeated info / warn logs for our internal creation of httpclients (TokenRefreshInterceptor) because we pass the factory to it. Also a user wouldn't see additional logs if they keep re-using the same KuberenetesClientBuilder to build clients - as the factory is held on the builder.

@metacosm metacosm marked this pull request as draft March 6, 2023 16:04
@metacosm metacosm marked this pull request as ready for review March 6, 2023 21:26
@manusa manusa force-pushed the client-selection branch from 6b3d3ab to d225086 Compare April 4, 2023 12:20
@manusa manusa added this to the 6.6.0 milestone Apr 4, 2023
@sonarqubecloud
Copy link

sonarqubecloud bot commented Apr 4, 2023

Kudos, SonarCloud Quality Gate passed!    Quality Gate passed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 0 Code Smells

94.3% 94.3% Coverage
0.0% 0.0% Duplication

@manusa manusa merged commit db2af2f into master Apr 4, 2023
@manusa manusa deleted the client-selection branch April 4, 2023 16:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Improve logging when multiple HTTP client factories are found
5 participants