- 
                Notifications
    
You must be signed in to change notification settings  - Fork 168
 
Simplify OpAmp client api #2408
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
base: main
Are you sure you want to change the base?
Conversation
| /** | ||
| * Sets factory function for creating {@link RequestService} instances form a given server URI. | ||
| */ | ||
| public static void setServiceFactory( | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR also moves RequestService back to internal package as most users won't be needing it.
I'm not too worried about the internal package, as this lib is not stable anyway, though I currently need to pass a custom service with a customized okhttp client instance to intercept all the requests, so having to rely on statics for this factory and within an experimental scope seems a bit unnecessarily inconvenient to me, given the current status of this lib.
What if this setter is moved into the builder and it's called from within the setEndpoint(URI) function instead? I agree there's value in having convenient functions such as setEndpoint(String/URI) so I was thinking if it could be done in a way that presents different options in the same place (the builder) and people would choose the one that better fits their needs by looking at the options from an ide autocomplete list.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the pattern we are using in the instrumentation repository to introduce experimental functionality. Vast majority of users shouldn't really need the RequestService abstraction. For your use case it doesn't really change much. You'd just change
requestService = HttpRequestService.create(OkHttpSender.create(connectivity.getUrl(), okhttpClient))
builder.setRequestService(requestService)to
Experimental.setServiceFactory(builder, endpoint -> HttpRequestService.create(OkHttpSender.create(endpoint, okhttpClient)));I'd say it isn't too bad usability wise. Explicitly having to go through a class named Experimental shouldn't be a problem for those who are fine with using classes from a package named internal.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it, thanks for the example. I agree it's not too bad, I just have the following questions:
- Why bothering with an experimental/hidden API when the whole lib is essentially experimental? Hiding RequestService away might just discourage people from using it, and I guess ideally people should use the apis to see if there're no issues with them. Though I guess there's also the counter argument that, if it's hidden, then we'll know if it's actually needed whenever people ask for it to be included in the "main api", is that the reason for hiding it?
 - I'm not sure about the vast majority not needing it. Without it, the only configuration for the OpAMP server connection they can provide is the URL, but what if they need other often needed features, such as payload compression, tls config, custom periodic request delay for when http is used?
 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why bothering with an experimental/hidden API when the whole lib is essentially experimental?
because eventually we'd like it to be not experimental, got to start from somewhere
I'm not sure about the vast majority not needing it. Without it, the only configuration for the OpAMP server connection they can provide is the URL, but what if they need other often needed features, such as payload compression, tls config, custom periodic request delay for when http is used?
we could expose these in the OpampClientBuilder and change the factory to BiFunction<URI, Options, RequestService>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
because eventually we'd like it to be not experimental, got to start from somewhere
This is the confusing part for me, I think we both want the same, but from my point of view, hiding the API away will actually slow this process down.
we could expose these in the OpampClientBuilder and change the factory to BiFunction<URI, Options, RequestService
Sounds good. Still, I'd suggest adding the factory method right away. If anything, having to provide a preconfigured object to do the network connectivity shouldn't be weird for OTel users, as that's essentially what we do with the [Signal]Exporters already. Also, the Options object would probably have to be an interface too, as there's not a full overlap across the options we can pass when using HTTP vs WebSocket.
| private long capabilities = 0; | ||
| private RequestService service = | ||
| HttpRequestService.create(OkHttpSender.create("http://localhost:4320/v1/opamp")); | ||
| private Function<URI, RequestService> serviceFactory = | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems a little unconventional in Java to use a function for this kind of thing. I'd prefer that we just stick with using a method...which I think can even be static.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently we allow users replace this factory function, so they could customize things. Ideally eventually this will go away when we can provide users an option to customize the okhttp client without having to mess with the RequestService or HttpSender implementations.
| 
           I gave a little more thought at it and I keep finding potential issues with this proposal. At first it seems quite nice for the simplicity that  
 I'm also finding it difficult to see why asking users to create a   | 
    
| 
           One of the guiding principles in the core and instrumentation repository is that there is a conscious effort to minimize the public api surface that the user can interact with. If a class is not supposed to be part of the public api it is made package private or moved to an internal package. If a class is not supposed to be extended it is made final. 
 My understanding is that  
 To me  
 I think it could be solved in multiple ways. If you want users building a websocket client only have access to websocket options then this would require subclassing or parameterizing the builder. Instead of just using  interface ConnectionFactory {
  HttpSender httpSender();
  WebSocket websocket();
}
...
void setConnectionFactory(new OkHttpConnectionFactory(client));I hope that now you see that   | 
    
          
 This is a very fair point. 
 I agree this is a good starting point. I'm not sure of all the things users would need to customize, but I am certain that it'll be more than just the URL, because it's already the case for Elastic's use cases, the one I mentioned for Android as well as other for Elastic's Java agent where they need to provide a custom http periodic polling mechanism, and I think we could also check out what's needed in the Go client in terms of configs, as it's been around longer than this one. So in other words, I'm certain that right now a simple  
 I agree with this, which is why I'm strongly against going with an  Based on that, I agree that it's not necessary to expose   | 
    
Simplify OpAmp client api by allowing user to specify an endpoint. We'll choose whether to use http or websocket based on the endpoint scheme. This way users don't need to create the
RequestServiceandOkHttpSenderorOkHttpWebSocketthemselves. This PR also movesRequestServiceback tointernalpackage as most users won't be needing it. For those who need to provide a customRequestServiceI have added an experimental api that lets users set a factoryFunction<URI, RequestService>for creatingRequestServiceinstances.