You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Retrofit的onFailure()中获取请求方法、端点及提交字段值

Retrofit错误追踪:获取请求方法、端点及提交字段

需求说明

我希望追踪所有Retrofit请求的错误,需要记录出现问题的请求方法、端点名称以及用户提交的字段值。

相关代码

UserServices.java

@GET("visit/current_checkin")
Call<ResponCurrentCheckIn> getCurrentCheckin(
        @Query("sdo_id") String sdoId
);

Retrofit调用代码

new ApiClient().getUserService(SplashActivity.this).getCurrentCheckin(sdoId)
        .enqueue(new Callback<ResponCurrentCheckIn>() {
            @Override
            public void onResponse(Call<ResponCurrentCheckIn> call, Response<ResponCurrentCheckIn> response) {
                if (response.isSuccessful()) {
                    // TODO
                }
            }

            @Override
            public void onFailure(Call<ResponCurrentCheckIn> call, Throwable t) {
                String message = t.getClass().getSimpleName() + "\n" + t.getMessage();
                loading(false, message);
                new LogTracking(SplashActivity.this).save(user, "SplashActivity.java", "GET /visit/current_checkin", t.getMessage(), "Error Backend", null);
            }
        });

ApiClient.java

public static Retrofit retrofit;
//    public static final String BASE_URL = "https://online.meval.id/v1/api/";
//    public static final String BASE_URL = "https://v2.meval.id/v1/api/";


public static Retrofit getRetrofitInstance(String baseUrl) {
    HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
    httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);

    OkHttpClient okHttpClient = new OkHttpClient.Builder()
            .addInterceptor(new Interceptor() {
                @Override
                public okhttp3.Response intercept(Chain chain) throws IOException {
                    Request originalRequest = chain.request();
                    Request newRequest = originalRequest.newBuilder()
                            .header("Accept", "application/json")
                            .header("Content-Type", "application/x-www-form-urlencoded")
                            .header("Authtoken", "MY-AUTHTOKEN")
                            .build();
                    return chain.proceed(newRequest);
                }
            })
            .readTimeout(60, TimeUnit.SECONDS)
            .writeTimeout(60, TimeUnit.SECONDS)
            .connectTimeout(60, TimeUnit.SECONDS)
            .addInterceptor(httpLoggingInterceptor)
            .build();

    if (retrofit == null) {
        retrofit = new Retrofit.Builder()
                .addConverterFactory(ScalarsConverterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .baseUrl(baseUrl)
                .client(okHttpClient)
                .build();
    }
    return retrofit;
}

public static UserServices getUserService(Context context){
    SharedPreferences preferences = context.getSharedPreferences(MyPreference.CONTAINER_PREFERENCE.toString(), Context.MODE_PRIVATE);

    UserServices userService = getRetrofitInstance(BASE_URL).create(UserServices.class);
    return userService;
}

问题

  1. 如何在onFailure()中获取请求方法名?例如:GET、POST、PUT等
  2. 如何在onFailure()中获取端点名称?例如:/visit/current_checkin
  3. 如何在onFailure()中获取用户提交的各字段值?例如:sdoId的值

我尝试通过Android Studio提示访问Throwable类,但未找到相关方法。

解决方案

1. 获取请求方法名

Retrofit的Call对象可关联到OkHttp的Request,通过request().method()直接拿到请求方法:

@Override
public void onFailure(Call<ResponCurrentCheckIn> call, Throwable t) {
    String method = call.request().method(); // 得到GET/POST/PUT等
    // 后续日志记录逻辑
}

2. 获取端点名称

方式一:从URL中截取

从Request拿到HttpUrl,结合BaseUrl截取相对路径:

@Override
public void onFailure(Call<ResponCurrentCheckIn> call, Throwable t) {
    HttpUrl url = call.request().url();
    String baseUrl = ApiClient.getRetrofitInstance(ApiClient.BASE_URL).baseUrl().toString();
    String endpoint = url.toString().replace(baseUrl, ""); // 得到/visit/current_checkin
    // 后续日志记录逻辑
}

方式二:通过Interceptor提前存入Tag

修改ApiClient中的Interceptor,将端点信息存入Request的Tag,后续直接读取:

.addInterceptor(new Interceptor() {
    @Override
    public okhttp3.Response intercept(Chain chain) throws IOException {
        Request originalRequest = chain.request();
        // 提取端点路径
        String endpoint = originalRequest.url().encodedPath();
        // 将端点存入request的tag
        Request newRequest = originalRequest.newBuilder()
                .header("Accept", "application/json")
                .header("Content-Type", "application/x-www-form-urlencoded")
                .header("Authtoken", "MY-AUTHTOKEN")
                .tag("endpoint", endpoint)
                .build();
        return chain.proceed(newRequest);
    }
})

在onFailure中获取:

String endpoint = (String) call.request().tag("endpoint");

3. 获取用户提交的字段值

方式一:调用时直接保留参数引用

在发起请求时保存需要记录的参数,在onFailure中直接使用:

final String currentSdoId = sdoId; // 保存参数引用
new ApiClient().getUserService(SplashActivity.this).getCurrentCheckin(currentSdoId)
        .enqueue(new Callback<ResponCurrentCheckIn>() {
            @Override
            public void onFailure(Call<ResponCurrentCheckIn> call, Throwable t) {
                // 直接使用currentSdoId
                new LogTracking(SplashActivity.this).save(user, "SplashActivity.java", "GET /visit/current_checkin", t.getMessage(), "Error Backend", currentSdoId);
            }
        });

方式二:从Request中解析参数

如果是GET请求,参数在URL的Query里,可通过HttpUrl的queryParameter方法获取:

@Override
public void onFailure(Call<ResponCurrentCheckIn> call, Throwable t) {
    HttpUrl url = call.request().url();
    String sdoId = url.queryParameter("sdo_id");
    // 其他参数用对应的key获取
}

如果是POST请求(表单或JSON),可在Interceptor中提前解析请求体并存入Tag,或使用OkHttp的工具类读取RequestBody内容。


内容的提问来源于stack exchange,提问作者Sasmita Novitasari

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 02:39:54