问题
So I'm trying to integrate Firebase performance for Http requests and add them manually as they show here (step 9).
I'm using Retrofit 2 and RxJava 2, so I had the idea of doing a custom operator, check code below:
Retrofit 2 Client
@GET("branch-{environment}/v2/branches")
fun getBranch(@Path("environment") environment: String, @Query("location") location: String, @Query("fulfilment_type") fulfilmentType: String): Single<Response<GetBranchResponse>>
RxJava Call to the Retrofit Client
private val client: BranchClient = clientFactory.create(urlProvider.apiUrl)
override fun getBranch(postCode: String, fulfilmentType: FulfilmentType): Single<GetBranchResponse> {
return client
.getBranch(environment, postCode.toUpperCase(), fulfilmentType.toString())
.lift(RxHttpPerformanceSingleOperator(URL?, METHOD?))
.map { it.body() }
.subscribeIO() //custom Kotlin extension
.observeMain() //custom Kotlin extension
...
}
RxJava 2 Custom Operator via lift:
class RxHttpPerformanceSingleOperator<T>(private val url: String, private val method: String) : SingleOperator<Response<T>, Response<T>> {
private lateinit var metric: HttpMetric
@Throws(Exception::class)
override fun apply(observer: SingleObserver<in Response<T>>): SingleObserver<in Response<T>> {
return object : SingleObserver<Response<T>> {
override fun onSubscribe(d: Disposable) {
metric = FirebasePerformance.getInstance().newHttpMetric(url,
method.toUpperCase())
metric.start()
observer.onSubscribe(d)
}
override fun onSuccess(t: Response<T>) {
observer.onSuccess(t)
//More info: https://firebase.google.com/docs/perf-mon/get-started-android
metric.setRequestPayloadSize(t.raw().body().contentLength())
metric.setHttpResponseCode(t.code())
metric.stop()
}
override fun onError(e: Throwable) {
observer.onError(e)
metric.stop()
}
}
}
So currently I'm not sure how it the proper way to get the URL and METHOD of the request (marked as URL? and METHOD? ) to send to the operator,
I need them on onSubscribe to start the metric.. and there I don't have the response with it...
Currently UGLYYYYYYYY my way to do it is:
Add to the Retrofit Client:
@GET("branch-{environment}/v2/branches")
fun getBranchURL(@Path("environment") environment: String, @Query("location") location: String, @Query("fulfilment_type") fulfilmentType: String): Call<JsonObject>
Add add the parameters as:
val request = client.getBranchURL(environment, postCode.toUpperCase(), fulfilmentType.toString()).request()
url = request.url().toString()
method = request.method()
This makes me have 2 entries on the Client for each request... which makes no sense.
Some helpful clues along the way: - How to get the request url in retrofit 2.0 with rxjava?
回答1:
Add a Retrofit Interceptor
to your HttpClient.Builder
with the FirebaseInstance
and generate your HttpMetrics
there:
class FirebasePerformanceInterceptor(val performanceInstance: FirebasePerformance) : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val request = chain.request()
//Get request values
val url = request.url().url()
val requestPayloadSize = request.body()?.contentLength() ?: 0L
val httpMethod = request.method()
//Initialize http trace
val trace = performanceInstance.newHttpMetric(url, httpMethod)
trace.setRequestPayloadSize(requestPayloadSize)
trace.start()
//Proceed
val response = chain.proceed(chain.request())
//Get response values
val responseCode = response.code()
val responsePayloadSize = response.body()?.contentLength() ?: 0L
//Add response values to trace and close it
trace.setHttpResponseCode(responseCode)
trace.setResponsePayloadSize(responsePayloadSize)
trace.stop()
return response
}
}
You can directly copy and paste this code and it will work. Enjoy!
回答2:
What I'm going to suggest doesn't necessarily goes to your approach, it's just a different way of thinking about what you're trying to accomplished.
I would suggest 2 different approaches:
- Create your own observer (So create a class that extends Observer) that receives a Retrofit Call object and do your firebase logic in the subscribeActual method.
- Use Aspectj to define an annotation that will be processed when the Retrofit call is about to be executed and you can do the firebase logic inside the Aspect. (I'm not sure how Aspectj and kotlin works tho)
来源:https://stackoverflow.com/questions/48332073/how-can-i-get-the-url-and-method-of-retrofit-request-on-onsubscribe-of-rxjava-2