You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何通过OkHttp拦截器将请求响应日志记录到Crashlytics?

Got it, let's tackle this problem step by step. You want to capture full OkHttp request/response logs (like the detailed ones Android Studio shows) and send them to Crashlytics—especially for those 500 errors your clients are seeing. Here's how to make it work:

First, Understand the Issue

When you log response directly via Log.d(), you only get a basic summary because Response.toString() only outputs high-level metadata. To get the full request/response details (headers, body, etc.), you need to explicitly collect that information, and you have two solid approaches to do this.


Approach 1: Reuse HttpLoggingInterceptor (Quick & Easy)

The HttpLoggingInterceptor you're already using can output full BODY level logs—we just need to redirect its output to Crashlytics instead of (or in addition to) Logcat.

Modify your getOkHttpClient() method to use a custom logger for the interceptor:

@Singleton @Provides OkHttpClient getOkHttpClient() {
    // Create a logger that sends logs to both Logcat and Crashlytics
    HttpLoggingInterceptor.Logger crashlyticsLogger = message -> {
        Log.d("OkHttp", message); // Keep Logcat output for debugging
        Crashlytics.log(message); // Send each log line to Crashlytics
    };

    HttpLoggingInterceptor logging = new HttpLoggingInterceptor(crashlyticsLogger);
    logging.setLevel(HttpLoggingInterceptor.Level.BODY);

    return new OkHttpClient.Builder()
            .addInterceptor(logging)
            .addInterceptor(new HeaderInterceptor())
            .build();
}

This will automatically send every detail of your requests and responses to Crashlytics. If you want to only log when errors occur (like 500s), you can combine this with a dedicated error-catching interceptor.


Approach 2: Custom Interceptor for Targeted Logging (Flexible)

If you want more control—like only capturing full logs when a 500 error happens—create a custom interceptor that builds the full request/response log manually. This ensures you don't flood Crashlytics with unnecessary logs for successful requests.

First, add this interceptor to your OkHttp client setup:

@Singleton @Provides OkHttpClient getOkHttpClient() {
    HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
    logging.setLevel(HttpLoggingInterceptor.Level.BODY);

    // Interceptor to capture logs for 500 errors
    Interceptor crashReportInterceptor = chain -> {
        Request request = chain.request();
        Response response = chain.proceed(request);

        // Only log when we get a 5xx server error
        if (response.code() >= 500) {
            try {
                String fullLog = buildFullRequestResponseLog(request, response);
                Crashlytics.log(fullLog);
                // Report as an exception to make it easy to find in Crashlytics
                Crashlytics.logException(new RuntimeException("Server Error " + response.code() + ": " + fullLog));
            } catch (IOException e) {
                Crashlytics.logException(e);
            }
        }

        return response;
    };

    return new OkHttpClient.Builder()
            .addInterceptor(logging)
            .addInterceptor(new HeaderInterceptor())
            .addInterceptor(crashReportInterceptor)
            .build();
}

// Helper method to build the full request/response log string
private String buildFullRequestResponseLog(Request request, Response response) throws IOException {
    StringBuilder logBuilder = new StringBuilder();

    // Log request details
    logBuilder.append("=== REQUEST ===\n")
            .append(request.method()).append(" ").append(request.url()).append("\n");
    // Request headers
    Headers reqHeaders = request.headers();
    for (int i = 0; i < reqHeaders.size(); i++) {
        logBuilder.append(reqHeaders.name(i)).append(": ").append(reqHeaders.value(i)).append("\n");
    }
    // Request body (if exists)
    if (request.body() != null) {
        Buffer buffer = new Buffer();
        request.body().writeTo(buffer);
        logBuilder.append("\nRequest Body:\n").append(buffer.readUtf8()).append("\n");
    }

    // Log response details
    logBuilder.append("\n=== RESPONSE ===\n")
            .append(response.code()).append(" ").append(response.message()).append("\n");
    // Response headers
    Headers resHeaders = response.headers();
    for (int i = 0; i < resHeaders.size(); i++) {
        logBuilder.append(resHeaders.name(i)).append(": ").append(resHeaders.value(i)).append("\n");
    }
    // Response body (use peekBody to avoid consuming the original stream)
    ResponseBody resBody = response.peekBody(Long.MAX_VALUE);
    if (resBody != null) {
        logBuilder.append("\nResponse Body:\n").append(resBody.string()).append("\n");
    }

    return logBuilder.toString();
}

Key Notes:

  • Use response.peekBody(Long.MAX_VALUE) instead of response.body().string()—this creates a copy of the response body so you can read it without breaking the original stream for Retrofit.
  • Crashlytics.log() works for plain text logs, while Crashlytics.logException() ties the log to an exception entry in Crashlytics, making it easier to track down 500 errors alongside other crashes.

Why Your Original Code Didn't Work

When you logged response directly, you were calling Response.toString(), which only outputs a brief summary of the response status and URL. The custom logic above explicitly collects headers, bodies, and other details to match the full logs you see in Android Studio.

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

火山引擎 最新活动