Java 使用改造 2 进行日志记录

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32514410/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 12:40:08  来源:igfitidea点击:

Logging with Retrofit 2

javaretrofitretrofit2okhttp3

提问by Gabor

I'm trying to get the exact JSON that is being sent in the request. Here is my code:

我正在尝试获取请求中发送的确切 JSON。这是我的代码:

OkHttpClient client = new OkHttpClient();
client.interceptors().add(new Interceptor(){
   @Override public com.squareup.okhttp.Response intercept(Chain chain) throws IOException {
      Request request = chain.request();
      Log.e(String.format("\nrequest:\n%s\nheaders:\n%s",
                          request.body().toString(), request.headers()));
      com.squareup.okhttp.Response response = chain.proceed(request);
      return response;
   }
});
Retrofit retrofit = new Retrofit.Builder()
   .baseUrl(API_URL)
   .addConverterFactory(GsonConverterFactory.create())
   .client(client).build();

But I only see this in the logs:

但我只在日志中看到这一点:

request:
com.squareup.okhttp.RequestBody@3ff4074d
headers:
Content-Type: application/vnd.ll.event.list+json

How am I supposed to do proper logging, given the removal of setLog()and setLogLevel()which we used to use with Retrofit 1?

考虑到我们曾经在 Retrofit 1 中使用setLog()和删除的内容,我应该如何进行正确的日志记录setLogLevel()

采纳答案by klimat

In Retrofit 2 you should use HttpLoggingInterceptor.

在 Retrofit 2 中,您应该使用HttpLoggingInterceptor

Add dependency to build.gradle. Latest version as of October 2019 is:

将依赖添加到build.gradle. 截至 2019 年 10 月的最新版本是:

implementation 'com.squareup.okhttp3:logging-interceptor:4.2.1'

Create a Retrofitobject like the following:

创建一个Retrofit对象,如下所示:

HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();

Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("https://backend.example.com")
        .client(client)
        .addConverterFactory(GsonConverterFactory.create())
        .build();

return retrofit.create(ApiClient.class);

In case of deprecation warnings, simply change setLevelto:

如果出现弃用警告,只需更改setLevel为:

interceptor.level(HttpLoggingInterceptor.Level.BODY);

The above solution gives you logcat messages very similar to the old ones set by

上述解决方案为您提供的 logcat 消息与设置的旧消息非常相似

setLogLevel(RestAdapter.LogLevel.FULL)

In case of java.lang.ClassNotFoundException:

在以下情况下java.lang.ClassNotFoundException

Older Retrofit version might require an older logging-interceptorversion. Take a look at comments sections for details.

较旧的 Retrofit 版本可能需要较旧的logging-interceptor版本。查看评论部分以了解详细信息。

回答by Vihuela Yao

hey guys,i already find solution:

嘿伙计们,我已经找到了解决方案:

  public static <T> T createApi(Context context, Class<T> clazz, String host, boolean debug) {
    if (singleton == null) {
        synchronized (RetrofitUtils.class) {
            if (singleton == null) {
                RestAdapter.Builder builder = new RestAdapter.Builder();
                builder
                        .setEndpoint(host)
                        .setClient(new OkClient(OkHttpUtils.getInstance(context)))
                        .setRequestInterceptor(RequestIntercepts.newInstance())
                        .setConverter(new GsonConverter(GsonUtils.newInstance()))
                        .setErrorHandler(new ErrorHandlers())
                        .setLogLevel(debug ? RestAdapter.LogLevel.FULL : RestAdapter.LogLevel.NONE)/*LogLevel.BASIC will cause response.getBody().in() close*/
                        .setLog(new RestAdapter.Log() {
                            @Override
                            public void log(String message) {
                                if (message.startsWith("{") || message.startsWith("["))
                                    Logger.json(message);
                                else {
                                    Logger.i(message);
                                }
                            }
                        });
                singleton = builder.build();
            }
        }
    }
    return singleton.create(clazz);
}

回答by oceanfeeling

I don't know if setLogLevel() will return in the final 2.0 version of Retrofit but for now you can use an interceptor for logging.

我不知道 setLogLevel() 是否会在 Retrofit 的最终 2.0 版本中返回,但现在您可以使用拦截器进行日志记录。

A good example can found in OkHttp wiki: https://github.com/square/okhttp/wiki/Interceptors

一个很好的例子可以在 OkHttp wiki 中找到:https: //github.com/square/okhttp/wiki/Interceptors

OkHttpClient client = new OkHttpClient();
client.interceptors().add(new LoggingInterceptor());

Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("http://www.yourjsonapi.com")
        .addConverterFactory(GsonConverterFactory.create())
        .client(client)
        .build();

回答by Anton Ryabyh

Try this:

尝试这个:

Request request = chain.request();
Buffer buffer = new Buffer();
request.body().writeTo(buffer);
String body = buffer.readUtf8();

After this, in the bodythere is the JSON you are interested in.

在此之后,body有您感兴趣的 JSON。

回答by david.mihola

Here is an Interceptorthat logs both the request and response bodies (using Timber, based on an example from the OkHttp docs and some other SO answers):

这是一个Interceptor记录请求和响应主体的日志(使用 Timber,基于 OkHttp 文档和其他一些 SO 答案中的示例):

public class TimberLoggingInterceptor implements Interceptor {
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();

        long t1 = System.nanoTime();
        Timber.i("Sending request %s on %s%n%s", request.url(), chain.connection(), request.headers());
        Timber.v("REQUEST BODY BEGIN\n%s\nREQUEST BODY END", bodyToString(request));

        Response response = chain.proceed(request);

        ResponseBody responseBody = response.body();
        String responseBodyString = response.body().string();

        // now we have extracted the response body but in the process
        // we have consumed the original reponse and can't read it again
        // so we need to build a new one to return from this method

        Response newResponse = response.newBuilder().body(ResponseBody.create(responseBody.contentType(), responseBodyString.getBytes())).build();

        long t2 = System.nanoTime();
        Timber.i("Received response for %s in %.1fms%n%s", response.request().url(), (t2 - t1) / 1e6d, response.headers());
        Timber.v("RESPONSE BODY BEGIN:\n%s\nRESPONSE BODY END", responseBodyString);

        return newResponse;
    }

    private static String bodyToString(final Request request){

        try {
            final Request copy = request.newBuilder().build();
            final Buffer buffer = new Buffer();
            copy.body().writeTo(buffer);
            return buffer.readUtf8();
        } catch (final IOException e) {
            return "did not work";
        }
    }
}

回答by DGN

For those who need high level logging in Retrofit, use the interceptor like this

对于那些需要在 Retrofit 中进行高级日志记录的人,可以像这样使用拦截器

public static class LoggingInterceptor implements Interceptor {
    @Override public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        long t1 = System.nanoTime();
        String requestLog = String.format("Sending request %s on %s%n%s",
                request.url(), chain.connection(), request.headers());
        //YLog.d(String.format("Sending request %s on %s%n%s",
        //        request.url(), chain.connection(), request.headers()));
        if(request.method().compareToIgnoreCase("post")==0){
            requestLog ="\n"+requestLog+"\n"+bodyToString(request);
        }
        Log.d("TAG","request"+"\n"+requestLog);

        Response response = chain.proceed(request);
        long t2 = System.nanoTime();

        String responseLog = String.format("Received response for %s in %.1fms%n%s",
                response.request().url(), (t2 - t1) / 1e6d, response.headers());

        String bodyString = response.body().string();

        Log.d("TAG","response"+"\n"+responseLog+"\n"+bodyString);

        return response.newBuilder()
                .body(ResponseBody.create(response.body().contentType(), bodyString))
                .build();
        //return response;
    }
}

public static String bodyToString(final Request request) {
    try {
        final Request copy = request.newBuilder().build();
        final Buffer buffer = new Buffer();
        copy.body().writeTo(buffer);
        return buffer.readUtf8();
    } catch (final IOException e) {
        return "did not work";
    }
}`

Courtesy: https://github.com/square/retrofit/issues/1072#

礼貌https: //github.com/square/retrofit/issues/1072#

回答by Anthonyeef

I met the thing as you and I tried to ask the author of the book Retrofit: Love working with APIs on Android(here is the link) (nope! I am not making some ads for them....but they are really nice guys :) And the author replied to me very soon, with both Log method on Retrofit 1.9 and Retrofit 2.0-beta.

我遇到了你和我试图问这本书的作者 Retrofit: Love working with APIs on Android(这是链接)(不!我没有为他们做一些广告......但他们真的很好伙计们 :) 作者很快就回复了我,在 Retrofit 1.9 和 Retrofit 2.0-beta 上都有 Log 方法。

And here is the code of Retrofit 2.0-beta:

这是 Retrofit 2.0-beta 的代码:

HttpLoggingInterceptor logging = new HttpLoggingInterceptor();  
// set your desired log level
logging.setLevel(Level.BODY);

OkHttpClient httpClient = new OkHttpClient();  
// add your other interceptors …

// add logging as last interceptor
httpClient.interceptors().add(logging);  // <-- this is the important line!

Retrofit retrofit = new Retrofit.Builder()  
   .baseUrl(API_BASE_URL)
   .addConverterFactory(GsonConverterFactory.create())
   .client(httpClient)
   .build();

This is how to add logging method with the help of HttpLoggingInterceptor. Also if you are the reader of that book I mentioned above, you may find that it says there is not log method with Retrofit 2.0 anymore -- which, I had asked the author, is not correct and they will update the book next year talking about it.

这是在HttpLoggingInterceptor的帮助下添加日志记录方法的方法。另外,如果你是我上面提到的那本书的读者,你可能会发现它说 Retrofit 2.0 不再有日志方法——我问过作者,这是不正确的,他们将在明年更新这本书关于它。

// In case you are not that familiar with the Log method in Retrofit, I would like to share something more.

// 如果你不太熟悉 Retrofit 中的 Log 方法,我想再分享一些东西。

Also should be noticed that there are some Logging Levels you could pick. I use the Level.BODYmost of the time, which will give some thing like this:

还应该注意的是,您可以选择一些日志记录级别。我大部分时间都在使用Level.BODY,它会给出这样的东西:

enter image description here

在此处输入图片说明

You can find almost all the http staff inside the picture: the header, the content and response, etc.

你可以在图片中找到几乎所有的http人员:头部、内容和响应等。

And sometimes you really don't need all the guests to attend your party: I just want to know whether it's successfully connected, that internet call is successfully made within my Activiy & Fragmetn. Then you are free to use Level.BASIC, which will return something like this:

有时你真的不需要所有的客人都参加你的派对:我只想知道它是否成功连接,互联网电话是否在我的 Activiy & Fragmetn 中成功进行。然后你可以自由使用Level.BASIC,它会返回如下内容:

enter image description here

在此处输入图片说明

Can you find the status code 200 OKinside? That is it :)

你能在里面找到状态码200 OK吗?这就对了 :)

Also there is another one, Level.HEADERS, which will only return the header of the network. Ya of course another picture here:

还有另一个,Level.HEADERS,它只会返回网络的标头。当然,这里还有另一张照片:

enter image description here

在此处输入图片说明

That's all of the Logging trick ;)

这就是所有的日志记录技巧;)

And I would like to share you with the tutorial I learned a lot there. They have a bunch of great post talking about almost everything related to Retrofit, and they are continuing updating the post, at the same time Retrofit 2.0 is coming. Please take a look at those work, which I think will save you lots of time.

而且我想用我学到了很多的教程分享你那里。他们有一堆很棒的帖子谈论几乎所有与 Retrofit 相关的内容,并且他们正在继续更新帖子,同时 Retrofit 2.0 即将到来。请看一下这些工作,我认为这会为您节省很多时间。

回答by Yazon2006

The main problem which I faced was dynamical adding headers and logging them into debug logcat. I've tried to add two interceptors. One for logging and one for adding headers on-the-go (token authorization). The problem was that we may .addInterceptor or .addNetworkInterceptor. As Jake Wharton said to me: "Network interceptors always come after application interceptors. See https://github.com/square/okhttp/wiki/Interceptors". So here is working example with headers and logs:

我面临的主要问题是动态添加标头并将它们记录到调试 logcat 中。我试图添加两个拦截器。一种用于日志记录,一种用于随时随地添加标头(令牌授权)。问题是我们可能是 .addInterceptor 或 .addNetworkInterceptor。正如 Jake Wharton 对我说的:“网络拦截器总是在应用程序拦截器之后。参见https://github.com/square/okhttp/wiki/Interceptors”。所以这是带有标题和日志的工作示例:

OkHttpClient httpClient = new OkHttpClient.Builder()
            //here we can add Interceptor for dynamical adding headers
            .addNetworkInterceptor(new Interceptor() {
                @Override
                public Response intercept(Chain chain) throws IOException {
                    Request request = chain.request().newBuilder().addHeader("test", "test").build();
                    return chain.proceed(request);
                }
            })
            //here we adding Interceptor for full level logging
            .addNetworkInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
            .build();

    Retrofit retrofit = new Retrofit.Builder()
            .addConverterFactory(GsonConverterFactory.create(gsonBuilder.create()))
            .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
            .client(httpClient)
            .baseUrl(AppConstants.SERVER_ADDRESS)
            .build();

回答by kenyee

You can also add Facebook's Stetho and look at the network traces in Chrome: http://facebook.github.io/stetho/

您还可以添加 Facebook 的 Stetho 并查看 Chrome 中的网络痕迹:http://facebook.github.io/stetho/

final OkHttpClient.Builder builder = new OkHttpClient.Builder();
if (BuildConfig.DEBUG) {
    builder.networkInterceptors().add(new StethoInterceptor());
}

Then open "chrome://inspect" in Chrome...

然后在 Chrome 中打开“chrome://inspect”...

回答by Nilesh Senta

I found way for Print Log in Retrofit

我在改造中找到了打印日志的方法

OkHttpClient okHttpClient = new OkHttpClient.Builder()
            .addInterceptor(new Interceptor() {
                @Override
                public Response intercept(Chain chain) throws IOException {
                    Request request = chain.request();
                    if (BuildConfig.DEBUG) {
                        Log.e(getClass().getName(), request.method() + " " + request.url());
                        Log.e(getClass().getName(), "" + request.header("Cookie"));
                        RequestBody rb = request.body();
                        Buffer buffer = new Buffer();
                        if (rb != null)
                            rb.writeTo(buffer);
                        LogUtils.LOGE(getClass().getName(), "Payload- " + buffer.readUtf8());
                    }
                    return chain.proceed(request);
                }
            })
            .readTimeout(60, TimeUnit.SECONDS)
            .connectTimeout(60, TimeUnit.SECONDS)
            .build();

            iServices = new Retrofit.Builder()
                    .baseUrl("Your Base URL")
                    .client(okHttpClient)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build()
                    .create(Your Service Interface .class);

Works for me.

为我工作。