Integrate with the OkHttp's analytics API
See original GitHub issueWhat kind of issue is this?
-
Question. This issue tracker is not the place for questions. If you want to ask how to do something, or to understand why something isn’t working the way you expect it to, use Stack Overflow. https://stackoverflow.com/questions/tagged/retrofit
-
Bug report. If you’ve found a bug, spend the time to write a failing test. Bugs with tests get fixed. Here’s an example: https://gist.github.com/swankjesse/6608b4713ad80988cdc9
-
Feature Request. Start by telling us what problem you’re trying to solve. Often a solution already exists! Don’t send pull requests to implement new features without first getting our support. Sometimes we leave features out on purpose to keep the project small.
Following the analytics API that is being build within okhttp (https://github.com/square/okhttp/issues/270), I would like to capture metrics per mapped path / route.
tl;dr
Currently it is not possible to have metrics per route in OkHttp’s EventListener
without parsing the URL against a known list of path (that has to populated from the interface or somewhere else.
This inefficient on several aspects.
I would like retrofit to communicate the route context to OkHttp, inorder to access the in the EventListener.
Example
That is for the following interface.
interface FakeRest {
@GET("/posts")
Call<ResponseBody> posts();
@GET("/posts/{post-id}")
Call<ResponseBody> post(@Path("post-id") int postId);
@GET("/posts/{post-id}/comments")
Call<ResponseBody> postComments(@Path("post-id") int postId);
}
I would like to access the method or a pre-built request/call context that the EventListener
can access. I’ve played around with the Retrofit builder using Call.Factory
, CallAdapter.Factory
but unfortunately I didn’t find a way to capture this information and to pass it in the HTTP Call Request.
I noticed the tag
field in OkHttp’s Request
, I know it’s not documented for this kind of usage, but it would helped me to bootstrap the idea.
What I tried (and it’s currently ugly and inelegant) :
Have a built retrofit.
Retrofit retrofit = new Retrofit.Builder().baseUrl("https://jsonplaceholder.typicode.com/").build();
Decorate each CallAdapter.Factory
in a new Retrofit created form the original one, and capture path information from annotations (possibly use baseUrl
as well).
Retrofit.Builder newBuilder = retrofit.newBuilder();
for (Factory callAdapterFactory : retrofit.callAdapterFactories()) {
newBuilder.addCallAdapterFactory(new Factory() {
@Override
public CallAdapter<Object, Object> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
String normalizedPath = normalizedPathFrom(annotations);
CallAdapter<Object, Object> callAdapter = (CallAdapter<Object, Object>) callAdapterFactory.get(returnType, annotations, retrofit);
return new CallAdapter<Object, Object>() {
...
@Override
public Object adapt(Call<Object> call) {
return callAdapter.adapt(wrapCall(call));
}
};
}
});
}
retrofit = newBuilder.build();
But the thing here is that I don’t get how to pass it to an OkHttp Request
. The Call
received in the adapt
method cannot be modified, wrapping it won’t work, because internally (in OkHttpCall
) retrofit will build his own immutable request that will be used for executing or enqueuing the actual request. Cloning is of course out of question, and duplicating it appears impossible because the constructors are not public.
Using the Call.Factory
is no help, because the this interface receives a pre-built request, so I cannot introduce a Call.Factory
decorator that capture the necessary annotations and pass them in the request tag.
To be able to customize request, I believe that either RequestBuilder
could be made an interface (and making the according modifications), or that RequestBuilder
accept some sort of RequestCustomizer
that can access the route context, either headers, path, query param names, interface method name, etc. and pass it to the OkHttp Request
.
Issue Analytics
- State:
- Created 5 years ago
- Comments:7 (3 by maintainers)
Just adding in my two cents here. We’d also love to be able to get at the method that was called on the interface.
Talking to @swankjesse about this internally, it sounds like he has some ideas for this that might involve being able to add a
retrofit.Call
into theokhttp.Response
tags, and then being able to pluck that metadata back out for use later.Will be released in 2.5.0 soon.