স্প্রিং রেস্টটেম্পলেট - কীভাবে সম্পূর্ণ ডিবাগিং / অনুরোধ / প্রতিক্রিয়াগুলিতে লগিং সক্ষম করবেন?


220

আমি কিছুক্ষণের জন্য স্প্রিং রেস্টটেম্পলেট ব্যবহার করে আসছি এবং যখন আমি এটির অনুরোধ এবং প্রতিক্রিয়াগুলি ডিবাগ করার চেষ্টা করছি তখন আমি ধারাবাহিকভাবে একটি প্রাচীরকে আঘাত করি। আমি "ভার্বোজ" বিকল্পটি চালু করার সাথে যখন কার্ল ব্যবহার করি তখন মূলত আমি একই জিনিসগুলি দেখতে চাই। উদাহরণ স্বরূপ :

curl -v http://twitter.com/statuses/public_timeline.rss

প্রেরিত ডেটা এবং প্রাপ্ত ডেটা (উভয় শিরোনাম, কুকিজ ইত্যাদি) প্রদর্শন করবে।

আমি সম্পর্কিত কিছু পোস্ট দেখেছি যেমন: স্প্রিং রেস্টটেম্পলেটটিতে আমি কীভাবে প্রতিক্রিয়া লগ করব? তবে আমি এই সমস্যাটি সমাধান করতে পারি নি।

এটি করার একটি উপায় হ'ল বাস্তবে রেস্টস্টেম্পলেট উত্স কোডটি পরিবর্তন করা এবং সেখানে কিছু অতিরিক্ত লগিং স্টেটমেন্ট যুক্ত করা, তবে আমি এই পদ্ধতিকে সত্যিই একটি শেষ অবলম্বন জিনিস বলে মনে করব। স্প্রিং ওয়েব ক্লায়েন্ট / রেস্টটেম্পলেটকে বলার কিছু উপায় থাকতে হবে যাতে সমস্ত কিছু বন্ধুত্বপূর্ণ উপায়ে লগ হয়।

আমার লক্ষ্যটি কোডের মতো করে এটি করতে সক্ষম হবেন:

restTemplate.put("http://someurl", objectToPut, urlPathValues);

এবং তারপরে লগ ফাইল বা কনসোলে একই ধরণের ডিবাগ তথ্য (যেমন আমি কার্লের সাথে পাই) পেতে। আমি বিশ্বাস করি যে স্প্রিং রেস্টটেম্পলেট ব্যবহার করে এবং সমস্যা আছে এমন যে কারও পক্ষে এটি অত্যন্ত কার্যকর হবে। আপনার রেস্টটাইমলেট সমস্যাগুলি ডিবাগ করতে কার্ল ব্যবহার করা ঠিক কাজ করে না (কিছু ক্ষেত্রে)।


30
2018 এ পড়া যে কাউকে সতর্কতা: এর কোনও সহজ উত্তর নেই!
ডেভিডফ্রান্সিস

3
সর্বাধিক সহজ উপায় অ্যাবস্ট্রাক্ট HTTPMessageConverter শ্রেণীর লেখার (...) পদ্ধতিতে ব্রেকপয়েন্ট ব্যবহার করা, একটি আউটপুটমেসেজ অবজেক্ট রয়েছে যেখানে আপনি ডেটা দেখতে পেলেন। পিএস আপনি মানটি অনুলিপি করতে পারেন এবং তারপরে এটি অনলাইন ফর্ম্যাটারের সাথে ফর্ম্যাট করতে পারেন।
সের্গে চেকারনভ

1
মনে হচ্ছে বসন্তে এটি করা সহজ হওয়া উচিত, তবে, উত্তরগুলি থেকে এখানে বিচার করা - কেস নয়। সুতরাং অন্য একটি সমাধান হ'ল স্প্রিংকে পুরোপুরি বাইপাস করা এবং অনুরোধ / প্রতিক্রিয়া ক্যাপচারের জন্য ফিডলারের মতো একটি সরঞ্জাম ব্যবহার করা।
মাইকেলেলোক


জুলাই 2019: এখনও এই প্রশ্নের কোনও সহজ সমাধান নেই, আমি নীচে আমার নিজের উত্তরটিতে অন্য 24 টি উত্তর (এখনও অবধি) এবং তাদের মন্তব্য এবং আলোচনার সংক্ষিপ্তসার দেওয়ার চেষ্টা করেছি । আশা করি এটা সাহায্য করবে.
ক্রিস

উত্তর:


206

ClientHttpRequestInterceptorঅনুরোধ এবং প্রতিক্রিয়া সনাক্ত করতে সম্পূর্ণ প্রয়োগের সাথে উদাহরণটি সম্পূর্ণ করতে :

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;

public class LoggingRequestInterceptor implements ClientHttpRequestInterceptor {

    final static Logger log = LoggerFactory.getLogger(LoggingRequestInterceptor.class);

    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        traceRequest(request, body);
        ClientHttpResponse response = execution.execute(request, body);
        traceResponse(response);
        return response;
    }

    private void traceRequest(HttpRequest request, byte[] body) throws IOException {
        log.info("===========================request begin================================================");
        log.debug("URI         : {}", request.getURI());
        log.debug("Method      : {}", request.getMethod());
        log.debug("Headers     : {}", request.getHeaders() );
        log.debug("Request body: {}", new String(body, "UTF-8"));
        log.info("==========================request end================================================");
    }

    private void traceResponse(ClientHttpResponse response) throws IOException {
        StringBuilder inputStringBuilder = new StringBuilder();
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(response.getBody(), "UTF-8"));
        String line = bufferedReader.readLine();
        while (line != null) {
            inputStringBuilder.append(line);
            inputStringBuilder.append('\n');
            line = bufferedReader.readLine();
        }
        log.info("============================response begin==========================================");
        log.debug("Status code  : {}", response.getStatusCode());
        log.debug("Status text  : {}", response.getStatusText());
        log.debug("Headers      : {}", response.getHeaders());
        log.debug("Response body: {}", inputStringBuilder.toString());
        log.info("=======================response end=================================================");
    }

}

তারপরে RestTemplateএকটি BufferingClientHttpRequestFactoryএবং ব্যবহার করে তাত্ক্ষণিকভাবে LoggingRequestInterceptor:

RestTemplate restTemplate = new RestTemplate(new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory()));
List<ClientHttpRequestInterceptor> interceptors = new ArrayList<>();
interceptors.add(new LoggingRequestInterceptor());
restTemplate.setInterceptors(interceptors);

BufferingClientHttpRequestFactoryপ্রয়োজন বোধ করা হয় হিসাবে আমরা উভয় আটককারী এবং প্রাথমিক কলিং কোড প্রতিক্রিয়া শরীর ব্যবহার করতে চান। ডিফল্ট বাস্তবায়ন কেবল একবার প্রতিক্রিয়া বডি পড়তে দেয়।


27
এটা ভুল. আপনি যদি স্ট্রিমটি পড়েন তবে অ্যাপ্লিকেশন কোডটি প্রতিক্রিয়াটি পড়তে সক্ষম হবে না।
জেমস ওয়াটকিন্স

28
আমরা রেস্টটাইমলেটটিকে একটি বাফারিং ক্লায়েন্টএইচটিপিআরকুয়েস্টফ্যাক্টরি দিয়েছি যাতে আমরা প্রতিক্রিয়াটি দু'বার পড়তে পারি।
সোফিয়েন জাগদৌদি

16
আমরা প্রায় 3 মাস ধরে এই কৌশলটি ব্যবহার করছি। এটি কেবলমাত্র BufferingClientHttpResponseWrapper@Sofienezaghdoudi এর ইঙ্গিত অনুসারে কনফিগার করা রেস্টস্টেম্পলেট নিয়ে কাজ করে । যাইহোক, বসন্তের মক সার্ভার কাঠামো ব্যবহার করে পরীক্ষাগুলি ব্যবহার করার সময় এটি কার্যকর হয় না যেহেতু MockRestServiceServer.createServer(restTemplate)অনুরোধফ্যাক্টরিতে ওভাররাইট করে InterceptingClientHttpRequestFactory
রুবেসএমএন

8
কৌশলটি ভাল, বাস্তবায়ন ভুল। 404 কেস, রেসপন্স.জেটবিডি () আইওএক্সেপশন নিক্ষেপ করুন -> আপনি কখনও লগ আউট করতে পারবেন না এবং সবচেয়ে খারাপ এটি আপনার পুনরায় কোডে রিসোর্স্যাক্সেসেক্সেপশন হয়ে যাবে,
রিসক্লিয়েন্টের

6
উত্তরের জন্য ধন্যবাদ. তবে একাধিক "log.debug" রাখার এটি খারাপ অভ্যাস কারণ এটি অনেকগুলি অন্যান্য লগতে ছড়িয়ে যেতে পারে। একটি একক লগ.ডিগব্যাগ নির্দেশ ব্যবহার করা আরও ভাল যাতে আপনি নিশ্চিত হন যে সবকিছু একই জায়গায় রয়েছে
ব্যবহারকারীর 2447161

127

স্প্রিং বুটে আপনি বৈশিষ্ট্যগুলিতে এটি সেট করে (বা অন্য 12 ফ্যাক্টর পদ্ধতি) সম্পূর্ণ অনুরোধ / প্রতিক্রিয়া পেতে পারেন

logging.level.org.apache.http=DEBUG

এই ফলাফল

-DEBUG .i.c.DefaultHttpClientConnectionOperator : Connecting to localhost/127.0.0.1:41827
-DEBUG .i.c.DefaultHttpClientConnectionOperator : Connection established 127.0.0.1:39546<->127.0.0.1:41827
-DEBUG o.a.http.impl.execchain.MainClientExec   : Executing request POST /v0/users HTTP/1.1
-DEBUG o.a.http.impl.execchain.MainClientExec   : Target auth state: UNCHALLENGED
-DEBUG o.a.http.impl.execchain.MainClientExec   : Proxy auth state: UNCHALLENGED
-DEBUG org.apache.http.headers                  : http-outgoing-0 >> POST /v0/users HTTP/1.1
-DEBUG org.apache.http.headers                  : http-outgoing-0 >> Content-Type: application/json;charset=UTF-8
-DEBUG org.apache.http.headers                  : http-outgoing-0 >> Content-Length: 56
-DEBUG org.apache.http.headers                  : http-outgoing-0 >> Host: localhost:41827
-DEBUG org.apache.http.headers                  : http-outgoing-0 >> Connection: Keep-Alive
-DEBUG org.apache.http.headers                  : http-outgoing-0 >> User-Agent: Apache-HttpClient/4.5.2 (Java/1.8.0_102)
-DEBUG org.apache.http.headers                  : http-outgoing-0 >> Accept-Encoding: gzip,deflate
-DEBUG org.apache.http.wire                     : http-outgoing-0 >> "POST /v0/users HTTP/1.1[\r][\n]"
-DEBUG org.apache.http.wire                     : http-outgoing-0 >> "Content-Type: application/json;charset=UTF-8[\r][\n]"
-DEBUG org.apache.http.wire                     : http-outgoing-0 >> "Content-Length: 56[\r][\n]"
-DEBUG org.apache.http.wire                     : http-outgoing-0 >> "Host: localhost:41827[\r][\n]"
-DEBUG org.apache.http.wire                     : http-outgoing-0 >> "Connection: Keep-Alive[\r][\n]"
-DEBUG org.apache.http.wire                     : http-outgoing-0 >> "User-Agent: Apache-HttpClient/4.5.2 (Java/1.8.0_102)[\r][\n]"
-DEBUG org.apache.http.wire                     : http-outgoing-0 >> "Accept-Encoding: gzip,deflate[\r][\n]"
-DEBUG org.apache.http.wire                     : http-outgoing-0 >> "[\r][\n]"
-DEBUG org.apache.http.wire                     : http-outgoing-0 >> "{"id":null,"email":"xenoterracide@gmail.com","new":true}"

এবং প্রতিক্রিয়া

-DEBUG .i.c.DefaultHttpClientConnectionOperator : Connecting to localhost/127.0.0.1:41827
-DEBUG .i.c.DefaultHttpClientConnectionOperator : Connection established 127.0.0.1:39546<->127.0.0.1:41827
-DEBUG o.a.http.impl.execchain.MainClientExec   : Executing request POST /v0/users HTTP/1.1
-DEBUG o.a.http.impl.execchain.MainClientExec   : Target auth state: UNCHALLENGED
-DEBUG o.a.http.impl.execchain.MainClientExec   : Proxy auth state: UNCHALLENGED
-DEBUG org.apache.http.headers                  : http-outgoing-0 >> POST /v0/users HTTP/1.1
-DEBUG org.apache.http.headers                  : http-outgoing-0 >> Content-Type: application/json;charset=UTF-8
-DEBUG org.apache.http.headers                  : http-outgoing-0 >> Content-Length: 56
-DEBUG org.apache.http.headers                  : http-outgoing-0 >> Host: localhost:41827
-DEBUG org.apache.http.headers                  : http-outgoing-0 >> Connection: Keep-Alive
-DEBUG org.apache.http.headers                  : http-outgoing-0 >> User-Agent: Apache-HttpClient/4.5.2 (Java/1.8.0_102)
-DEBUG org.apache.http.headers                  : http-outgoing-0 >> Accept-Encoding: gzip,deflate
-DEBUG org.apache.http.wire                     : http-outgoing-0 >> "POST /v0/users HTTP/1.1[\r][\n]"
-DEBUG org.apache.http.wire                     : http-outgoing-0 >> "Content-Type: application/json;charset=UTF-8[\r][\n]"
-DEBUG org.apache.http.wire                     : http-outgoing-0 >> "Content-Length: 56[\r][\n]"
-DEBUG org.apache.http.wire                     : http-outgoing-0 >> "Host: localhost:41827[\r][\n]"
-DEBUG org.apache.http.wire                     : http-outgoing-0 >> "Connection: Keep-Alive[\r][\n]"
-DEBUG org.apache.http.wire                     : http-outgoing-0 >> "User-Agent: Apache-HttpClient/4.5.2 (Java/1.8.0_102)[\r][\n]"
-DEBUG org.apache.http.wire                     : http-outgoing-0 >> "Accept-Encoding: gzip,deflate[\r][\n]"
-DEBUG org.apache.http.wire                     : http-outgoing-0 >> "[\r][\n]"
-DEBUG org.apache.http.wire                     : http-outgoing-0 >> "{"id":null,"email":"xenoterracide@gmail.com","new":true}"

বা ঠিক logging.level.org.apache.http.wire=DEBUGযা প্রাসঙ্গিক সমস্ত তথ্য ধারণ করে


4
এটি ছিল সবচেয়ে সহজ জিনিস যা আমি যা চাইছিলাম তা করল। আমি গ্রহণযোগ্য উত্তরে এটি সহ অত্যন্ত উত্সাহিত করি।
মাইচাভিলা

22
এর javadoc মতে RestTemplate :by default the RestTemplate relies on standard JDK facilities to establish HTTP connections. You can switch to use a different HTTP library such as Apache HttpComponents
Ortomala Lokni

22
@ অরটোমালা লকনি দ্বারা নির্দেশিত অনুসারে রেস্টটাইপলেট এই অ্যাপাচি ক্লাসগুলি ডিফল্ট হিসাবে ব্যবহার করবে না , সুতরাং যখন সেগুলি ব্যবহার করা হচ্ছে তখন কীভাবে ডিবাগ প্রিন্ট করা যায় সেগুলি ছাড়াও কীভাবে সেগুলি ব্যবহার করবেন তাও আপনার অন্তর্ভুক্ত করা উচিত ।
ক্যাপ্টেন ম্যান

আমি http-outgoing-0 << "[0x1f][0x8b][0x8][0x0][0x0][0x0][0x0][0x0]
এরকমই

2
@ পার্থসারথী ঘোষ সামগ্রীটি সম্ভবত জিজিপ এনকোডযুক্ত যার কারণে আপনি কাঁচা পাঠ্যটি দেখছেন না।
ম্যাথু বেকেট

80

কিছু কোড সহ @hstoerr উত্তর বাড়ানো হচ্ছে:


অনুরোধের প্রতিক্রিয়াগুলিতে লগ করতে লগিং -রেকুয়েস্টইন্টারসেপ্টর তৈরি করুন

public class LoggingRequestInterceptor implements ClientHttpRequestInterceptor {

    private static final Logger log = LoggerFactory.getLogger(LoggingRequestInterceptor.class);

    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {

        ClientHttpResponse response = execution.execute(request, body);

        log(request,body,response);

        return response;
    }

    private void log(HttpRequest request, byte[] body, ClientHttpResponse response) throws IOException {
        //do logging
    }
}

রেস্টটেম্পলেট সেটআপ করুন

RestTemplate rt = new RestTemplate();

//set interceptors/requestFactory
ClientHttpRequestInterceptor ri = new LoggingRequestInterceptor();
List<ClientHttpRequestInterceptor> ris = new ArrayList<ClientHttpRequestInterceptor>();
ris.add(ri);
rt.setInterceptors(ris);
rt.setRequestFactory(new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory());

এটি বসন্ত -৩.১ সংস্করণ না পাওয়া যায় না।
জ্ঞান

3
এটি 'লগিং প্রতিক্রিয়া' এর প্রশ্নের উত্তর দেয় না, তবে পরিবর্তে একটি // কর লগিং মন্তব্য করুন।
জিয়াং ওয়াইডি

1
লগিং করা সহজ ছিল, তবে এটি কেবল অনুরোধের জন্যই কাজ করে, আমি প্রতিক্রিয়াশীল সংস্থাগুলি দেখতে পাচ্ছি না, ধরুন আমার কাছে প্রতিক্রিয়াযুক্ত বস্তু রয়েছে, তবে এটির স্ট্রিমটি পড়া ভাল ধারণা নয়।
পাভেল নিডোবা

11
@ পাভেলনিডোবা বাফারক্লিয়েন্টএইচটিপিআরকুয়েস্টফ্যাক্টরি প্রতিক্রিয়াটিকে একাধিকবার পড়তে দেয়।
mjj1409

2
যদি আপনার ডিবাগিংয়ের জন্য কোনও ডাটাবেসে অনুরোধ / প্রতিক্রিয়া সম্পর্কিত তথ্য সংরক্ষণ করতে হয় এবং নিয়মিত লগিং আপনার প্রয়োজনের সাথে খাপ খায় না তবে এটি ভাল কাজ করে।
গেমসলুটস

32

আপনার সেরা বাজি ফাইল যোগ logging.level.org.springframework.web.client.RestTemplate=DEBUGকরা হয় application.properties

সেটিংয়ের মতো অন্যান্য সমাধানগুলি log4j.logger.httpclient.wireসর্বদা কার্যকর হয় না কারণ তারা ধরে নেয় যে আপনি ব্যবহার করেন log4jএবং অ্যাপাচি HttpClientযা সর্বদা সত্য নয়।

তবে দ্রষ্টব্য যে এই বাক্য গঠনটি কেবল স্প্রিং বুটের সর্বশেষতম সংস্করণগুলিতে কাজ করবে।


5
এই অনুরোধটি এবং প্রতিক্রিয়া শরীর, শুধু URL এবং অনুরোধ প্রকার (বসন্ত ওয়েব-4.2.6) লগিং করা হয় না
Dve

1
আপনি ঠিক বলেছেন, এটি কোনও wireলগিং নয়, এটিতে কেবল ইউআরএল, রিসপোন কোড, পোষ্ট প্যারামিটার ইত্যাদির মতো প্রয়োজনীয় তথ্য অন্তর্ভুক্ত রয়েছে
গামেলিলা

1
আপনি কি সত্যিই চান এই হল stackoverflow.com/a/39109538/206466
xenoterracide

এটি ঠিক আছে তবে প্রতিক্রিয়া বডিটি দেখা যায়নি!
সানলিও

উজ্জ্বল। যদিও এটি প্রতিক্রিয়া বডিটি মুদ্রণ করে না, এটি এখনও খুব দরকারী। ধন্যবাদ.
ক্রিস

30

এই উত্তরগুলির কোনোটাই আসলে 100% সমস্যার সমাধান করে না। mjj1409 এর বেশিরভাগ অংশ পায়, তবে প্রতিক্রিয়াটি লগ করার বিষয়টি স্বাচ্ছন্দ্যে এড়িয়ে চলে যা আরও কিছুটা কাজ নেয়। পল সাউউ এমন একটি সমাধান সরবরাহ করেছেন যা বাস্তববাদী বলে মনে হয় তবে বাস্তবায়নের জন্য পর্যাপ্ত বিবরণ দেয় না (এবং এটি আমার পক্ষে মোটেও কার্যকর হয়নি)। সোফিয়েন লগিংটি পেয়েছে তবে একটি জটিল সমস্যা সহ: প্রতিক্রিয়াটি আর পঠনযোগ্য নয় কারণ ইতিমধ্যে ইনপুট স্ট্রিমটি গ্রাস হয়ে গেছে!

আমি প্রতিক্রিয়ার মূল অংশটি একাধিকবার পড়ার অনুমতি দেওয়ার জন্য প্রতিক্রিয়া অবজেক্টটি মোড়ানোর জন্য একটি বাফারিংক্লিয়েন্টএইচটিপি রেসপন্সওয়্যারার ব্যবহার করার পরামর্শ দিচ্ছি:

public class LoggingRequestInterceptor implements ClientHttpRequestInterceptor {

    private static final Logger logger = LoggerFactory.getLogger(LoggingRequestInterceptor.class);

    @Override
    public ClientHttpResponse intercept(final HttpRequest request, final byte[] body,
            final ClientHttpRequestExecution execution) throws IOException {
        ClientHttpResponse response = execution.execute(request, body);

        response = log(request, body, response);

        return response;
    }

    private ClientHttpResponse log(final HttpRequest request, final byte[] body, final ClientHttpResponse response) {
        final ClientHttpResponse responseCopy = new BufferingClientHttpResponseWrapper(response);
        logger.debug("Method: ", request.getMethod().toString());
        logger.debug("URI: ", , request.getURI().toString());
        logger.debug("Request Body: " + new String(body));
        logger.debug("Response body: " + IOUtils.toString(responseCopy.getBody()));
        return responseCopy;
    }

}

এটি ইনপুট স্ট্রিম গ্রহণ করবে না কারণ প্রতিক্রিয়া বডি মেমরিতে লোড হয়ে গেছে এবং একাধিকবার পড়তে পারে। আপনার ক্লাসপথে যদি আপনার বাফারিংক্লিয়েন্টএইচটিটিপ্রেসপন্স র‍্যাপার না থাকে তবে আপনি এখানে সহজ বাস্তবায়নটি খুঁজে পেতে পারেন:

https://github.com/spring-projects/spring-android/blob/master/spring-android-rest-template/src/main/java/org/springframework/http/client/BufferingClientHttpResponseWrapper.java

রেস্ট টেম্পলেট সেট আপ করার জন্য:

LoggingRequestInterceptor loggingInterceptor = new LoggingRequestInterceptor();
restTemplate.getInterceptors().add(loggingInterceptor);

একই, রেসপন্স.কপি.বিডিবিডি () 404 এর ক্ষেত্রে আইওক্সেপশন নিক্ষেপ করবে, যাতে আপনি আপনার পরবর্তী কোডটিতে কখনও প্রতিক্রিয়া পাঠান না এবং সাধারণত রেস্টক্লিয়েন্টের রিসপন্স এক্সসেপশন একটি রিসোর্সএ্যাকসেসেপ্সেপশন হয়ে যায়
মিলাচ

1
আপনার status==200আগে যাচাই করা উচিতresponseCopy.getBody()
আনন্দ রকজ

4
তবে এটি প্যাকেজ-প্রাইভেট। আপনি কি আপনার লগিংআরকিউস্টিইন্টারসেপ্টরটিকে 'org.springframework.http.client' প্যাকেজে রেখেছেন?
zbstof

2
কি asyncRestTemplate? এটির জন্য ListenableFutureযখন BufferingClientHttpResponseWrapperকোনও কলব্যাকের মাধ্যমে পরিবর্তন করা সম্ভব নয় তখন এটির জন্য আপনাকে ফিরে আসতে হবে ।
Farমার ফারুক আলমালি

@ FmerFarukAlmalı সেক্ষেত্রে আপনার পেয়ারা যে সংস্করণটি ব্যবহার করছেন তার উপর নির্ভর করে আপনাকে চেইন ব্যবহার করতে হবে বা রূপান্তর করতে হবে। দেখুন: স্ট্যাকওভারফ্লো.com
জেমস ওয়াটকিন্স

29

Xenoterracide ব্যবহার করার জন্য প্রদত্ত সমাধান

logging.level.org.apache.http=DEBUG

ভাল তবে সমস্যাটি হ'ল ডিফল্টরূপে অ্যাপাচি এইচটিটিপি কম্পোনেন্ট ব্যবহার করা হয় না।

অ্যাপাচি ব্যবহার করার জন্য এইচটিটিপি কম্পোনেন্টগুলি আপনার পম.এক্সএমএল যুক্ত করুন

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpasyncclient</artifactId>
</dependency>

এবং এর সাথে কনফিগার করুন RestTemplate:

RestTemplate restTemplate = new RestTemplate();
restTemplate.setRequestFactory(new HttpComponentsAsyncClientHttpRequestFactory());

সবচেয়ে সহজ উপায়, আমি কেবল যুক্ত করব যে এটি মকরেস্ট সার্ভিস সার্ভারের সাথে কাজ করে না, কারণ এটি অনুরোধের ফ্যাক্টিকে ওভাররাইট করে।
zbstof

ভাল কাজ করা এবং কোন সমস্যা কম কনফিগার!
sunleo

29

আপনি HTTP ট্র্যাফিক লগ করতে স্প্রিং-রেস্ট-টেম্পলেট-লগার ব্যবহার করতে পারেন RestTemplate

আপনার মাভেন প্রকল্পে একটি নির্ভরতা যুক্ত করুন:

<dependency>
    <groupId>org.hobsoft.spring</groupId>
    <artifactId>spring-rest-template-logger</artifactId>
    <version>2.0.0</version>
</dependency>

তারপরে আপনার কাস্টমাইজটি RestTemplateনিম্নরূপ করুন:

RestTemplate restTemplate = new RestTemplateBuilder()
    .customizers(new LoggingCustomizer())
    .build()

ডিবাগ লগিং এতে সক্ষম হয়েছে তা নিশ্চিত করুন application.properties:

logging.level.org.hobsoft.spring.resttemplatelogger.LoggingCustomizer = DEBUG

এখন সমস্ত রেস্টটেম্পলেট এইচটিটিপি ট্র্যাফিক org.hobsoft.spring.resttemplatelogger.LoggingCustomizerডিবাগ স্তরে লগইন হবে ।

অস্বীকৃতি: আমি এই গ্রন্থাগারটি লিখেছি।


এই উত্তরটি কেন নিম্নমানের হয়? এটা আমাকে সাহায্য করেছে। ধন্যবাদ, @ মার্ক হবসন
রাফেল বেচারা রামহে

3
খুশি এটি @ রাফেলবেচারারামে সাহায্য করেছে helped এটি প্রাথমিকভাবে ডাউনভোট হয়েছিল কারণ আমি লিঙ্কযুক্ত প্রকল্পের নির্দেশাবলী এম্বেড করিনি। আপনি যদি এটি দরকারী মনে করেন তবে নির্দ্বিধায় আপভোট করুন!
মার্ক হবসন

আপনি গ্র্যাডলের মাধ্যমে সমর্থন করেন?
ব্ল্যাকহ্যাটসামুরাই

1
@ ব্ল্যাকহ্যাটসামুরাই স্প্রিং-রেস্ট-টেম্পলেট-লগার একটি নিয়মিত মাভেন আর্টফ্যাক্ট, তাই গ্র্যাডলের সাথে এটি কাজ করা উচিত।
মার্ক হবসন

1
হাই @ এরহানাসিকোগলু, আপনাকে স্বাগতম! এটি ঠিক আছে, আপনি এটি ব্যবহারের জন্য এখানে দেখতে পাবেন: github.com/markhobson/spring-rest-template-logger/blob/master/…
মার্ক হবসন

26

অবশেষে আমি সঠিক উপায়ে এটি করার একটি উপায় খুঁজে পেয়েছি। বেশিরভাগ সমাধান আসে কীভাবে আমি স্প্রিং এবং এসএলএফ 4 জে কনফিগার করব যাতে আমি লগইন করতে পারি?

দেখে মনে হচ্ছে দুটি কাজ করা দরকার:

  1. Log4j.properties এ নিম্নলিখিত লাইন যুক্ত করুন: log4j.logger.httpclient.wire=DEBUG
  2. নিশ্চিত করুন যে বসন্ত আপনার লগিং কনফিগারটিকে উপেক্ষা করে না

দ্বিতীয় সমস্যাটি বেশিরভাগ ক্ষেত্রে বসন্তের পরিবেশগুলির ক্ষেত্রে ঘটে যেখানে slf4j ব্যবহৃত হয় (এটি আমার ক্ষেত্রে যেমন ছিল)। যেমন, যখন slf4j ব্যবহার করা হয় তা নিশ্চিত করে নিন যে নিম্নলিখিত দুটি জিনিস ঘটেছে:

  1. আপনার ক্লাসপথে কোনও কমন্স-লগিং গ্রন্থাগার নেই: এটি আপনার পোমে বর্জন বর্ণনাকারী যুক্ত করে করা যেতে পারে:

            <exclusions><exclusion>
                <groupId>commons-logging</groupId>
                <artifactId>commons-logging</artifactId>
            </exclusion>
        </exclusions>
  2. লগ 4j.properties ফাইলটি ক্লাসপথে কোথাও সঞ্চিত আছে যেখানে বসন্ত এটি দেখতে বা দেখতে পারে। আপনার যদি এটির সাথে সমস্যা হয় তবে একটি শেষ সমাধান সমাধান হ'ল লগ 4j.properties ফাইলটি ডিফল্ট প্যাকেজে রেখে দেওয়া (একটি ভাল অনুশীলন নয় তবে কেবলমাত্র আপনার প্রত্যাশা অনুযায়ী জিনিসগুলি কাজ করে তা দেখতে)


7
এটি আমার পক্ষে কাজ করে না, আমি দুটি জিনিসই করেছি। আমি বুঝতে পারছি না যে আমার প্রকল্পে যেভাবেই এটি ব্যবহার করা হয় না কেন আমার লগ 4 জে.প্রপ্রেটিস লাগানো দরকার (এমভিএন নির্ভরতা দ্বারা পরীক্ষা করা হয়: গাছ)
পাভেল নিডোবা

এটি আমার পক্ষেও কাজ করে না। এমনকি আমি ডিফল্ট মোডে রুট লগার সেট করার চেষ্টা করেছি এবং এখনও কিছুই নেই।
জেমস ওয়াটকিন্স

"httpclient.wire.content" এবং "httpclient.wire.header" হ'ল অক্ষ 2 এর কাঠামোর লগার নাম names এগুলিকে অ্যাক্সিস 2 ব্যবহার করে করা হয় তবে একটি স্প্রিং প্রকল্পে যেমন SOAP অনুরোধগুলি লগ করতে ব্যবহার করা যেতে পারে ।
লাথস্পেল

11
httpclient.wireআসলে অ্যাপাচি এইচটিপিপি কম্পোনেন্টস এইচটিটিপি ক্লায়েন্ট লাইব্রেরি থেকে এসেছে (দেখুন hc.apache.org/httpcomponents-client-ga/logging.html )। এই কৌশলটি কেবল তখনই কাজ করবে যদি আপনি RestTemplateHttpComponentsClientHttpRequestFactory
স্কট ফ্রেডরিক

21

লগিং রেস্টটেম্পলেট

বিকল্প 1. ডিবাগ লগিং খুলুন।

রেস্টটেম্পলেট কনফিগার করুন

  • ডিফল্টরূপে রেস্টটেম্পলেট এইচটিটিপি সংযোগ স্থাপনের জন্য স্ট্যান্ডার্ড জেডিকে সুবিধার উপর নির্ভর করে। আপনি অন্য একটি এইচটিটিপি লাইব্রেরি যেমন অ্যাপাচি এইচটিপিপি কম্পোনেন্টস ব্যবহার করতে স্যুইচ করতে পারেন

    @ বিয়ান পাবলিক রেস্টটেম্পলেট রেস্টটেম্পলেট (রেস্টটেম্পলেটবিল্ডার বিল্ডার) {রেস্টটেম্পলেট রেস্টটেম্পলেট = বিল্ডার.বিল্ড (); রিটার্ন রিস্টেম্পলেট; }

লগিং কনফিগার করুন

  • application.yml

    লগিং: স্তর: org.springframework.web.client.RestTemplate: DEBUG

বিকল্প 2 ইন্টারসেপ্টর ব্যবহার করে

মোড়ানো প্রতিক্রিয়া

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;

import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.util.StreamUtils;

public final class BufferingClientHttpResponseWrapper implements ClientHttpResponse {

    private final ClientHttpResponse response;

    private byte[] body;


    BufferingClientHttpResponseWrapper(ClientHttpResponse response) {
        this.response = response;
    }

    public HttpStatus getStatusCode() throws IOException {
        return this.response.getStatusCode();
    }

    public int getRawStatusCode() throws IOException {
        return this.response.getRawStatusCode();
    }

    public String getStatusText() throws IOException {
        return this.response.getStatusText();
    }

    public HttpHeaders getHeaders() {
        return this.response.getHeaders();
    }

    public InputStream getBody() throws IOException {
        if (this.body == null) {
            this.body = StreamUtils.copyToByteArray(this.response.getBody());
        }
        return new ByteArrayInputStream(this.body);
    }

    public void close() {
        this.response.close();
    }
}

ইন্টারসেপ্টর প্রয়োগ করুন

package com.example.logging;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;

public class LoggingRestTemplate implements ClientHttpRequestInterceptor {

    private final static Logger LOGGER = LoggerFactory.getLogger(LoggingRestTemplate.class);

    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body,
            ClientHttpRequestExecution execution) throws IOException {
        traceRequest(request, body);
        ClientHttpResponse response = execution.execute(request, body);
        return traceResponse(response);
    }

    private void traceRequest(HttpRequest request, byte[] body) throws IOException {
        if (!LOGGER.isDebugEnabled()) {
            return;
        }
        LOGGER.debug(
                "==========================request begin==============================================");
        LOGGER.debug("URI                 : {}", request.getURI());
        LOGGER.debug("Method            : {}", request.getMethod());
        LOGGER.debug("Headers         : {}", request.getHeaders());
        LOGGER.debug("Request body: {}", new String(body, "UTF-8"));
        LOGGER.debug(
                "==========================request end================================================");
    }

    private ClientHttpResponse traceResponse(ClientHttpResponse response) throws IOException {
        if (!LOGGER.isDebugEnabled()) {
            return response;
        }
        final ClientHttpResponse responseWrapper = new BufferingClientHttpResponseWrapper(response);
        StringBuilder inputStringBuilder = new StringBuilder();
        BufferedReader bufferedReader = new BufferedReader(
                new InputStreamReader(responseWrapper.getBody(), "UTF-8"));
        String line = bufferedReader.readLine();
        while (line != null) {
            inputStringBuilder.append(line);
            inputStringBuilder.append('\n');
            line = bufferedReader.readLine();
        }
        LOGGER.debug(
                "==========================response begin=============================================");
        LOGGER.debug("Status code    : {}", responseWrapper.getStatusCode());
        LOGGER.debug("Status text    : {}", responseWrapper.getStatusText());
        LOGGER.debug("Headers            : {}", responseWrapper.getHeaders());
        LOGGER.debug("Response body: {}", inputStringBuilder.toString());
        LOGGER.debug(
                "==========================response end===============================================");
        return responseWrapper;
    }

}

রেস্টটেম্পলেট কনফিগার করুন

@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
    RestTemplate restTemplate = builder.build();
    restTemplate.setInterceptors(Collections.singletonList(new LoggingRestTemplate()));
    return restTemplate;
}

লগিং কনফিগার করুন

  • লগিংরেস্টটেমপ্লেটের প্যাকেজটি পরীক্ষা করুন, উদাহরণস্বরূপ application.yml:

    লগিং: স্তর: com.example.logging: DEBUG

অপশন ৩

আমদানি করুন http কম্পোনেন্ট নির্ভরতা

<dependency>
  <groupId>org.apache.httpcomponents</groupId>
  <artifactId>httpasyncclient</artifactId>

রেস্টটেম্পলেট কনফিগার করুন

@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
    RestTemplate restTemplate = builder.build();
    restTemplate.setRequestFactory(new HttpComponentsAsyncClientHttpRequestFactory());
    return restTemplate;
}

লগিং কনফিগার করুন

  • লগিংরেস্টটেমপ্লেটের প্যাকেজটি পরীক্ষা করুন, উদাহরণস্বরূপ application.yml:

    লগিং: স্তর: org.apache.http: DEBUG


কেবলমাত্র নোট করুন: আপনি কনফিগার করতে চান TestRestTemplate, কনফিগার করতে চাইলে RestTemplateBuilder: @ বিজন পাবলিক রেস্টটেম্পলেটবিল্ডার রিসটেম্পলেটবিল্ডার () {নতুন রেস্টটেম্পলেটবিল্ডার () ফেরান }
কিংওলেগ

সেই নতুন ইনপুটস্ট্রিম রিডার (প্রতিক্রিয়াআপনার.সেটবিডি (), স্ট্যান্ডার্ডচ্যারসেটস.উটিএফ_8)) নোট করুন; "অন্য প্রান্ত" ত্রুটি ফিরিয়ে দিলে একটি ত্রুটি ফেলতে পারে। আপনি এটিকে একটি চেষ্টা ব্লকের মধ্যে রাখতে চাইতে পারেন।
পিটারএস

15

---- জুলাই 2019 ----

(স্প্রিং বুট ব্যবহার করে)

আমি অবাক হয়েছিলাম যে স্প্রিং বুট, এটির জিরো কনফিগারেশনের যাদুগুলির সাথেও, রেস্টটেম্প্লেট সহ সাধারণ জেএসওএন প্রতিক্রিয়া বডিটি পরীক্ষা বা লগ করার কোনও সহজ উপায় সরবরাহ করে না। আমি এখানে সরবরাহিত বিভিন্ন উত্তর এবং মন্তব্যগুলি সন্ধান করেছি এবং আমার (এখনও) কী কাজ করে তার নিজস্ব পাতিত সংস্করণটি ভাগ করছি এবং আমার কাছে বর্তমান বিকল্পগুলি প্রদত্ত একটি যুক্তিসঙ্গত সমাধানের মতো বলে মনে হচ্ছে (আমি গ্রেডেল ৪.৪ সহ স্প্রিং বুট ২.১..6 ব্যবহার করছি) )

ফিডলারকে এইচটিপি প্রক্সি হিসাবে ব্যবহার করা

এটি আসলে বেশ মার্জিত সমাধান, কারণ এটি আপনার নিজের ইন্টারসেপ্টর তৈরি করার বা অন্তর্নিহিত HTTP ক্লায়েন্টকে অ্যাপাচে (নীচে দেখুন) পরিবর্তন করার সমস্ত জটিল প্রচেষ্টাকে অতিক্রম করে।

ফিডলার ইনস্টল করুন এবং চালান

এবং তারপর

যোগ -DproxySet=true -Dhttp.proxyHost=localhost -Dhttp.proxyPort=8888আপনার VM- র Options এ

2. অ্যাপাচি এইচটিপিপিলেট ব্যবহার করে

আপনার মাভেন বা গ্রেডল নির্ভরতাগুলিতে অ্যাপাচি এইচটিটিপি ক্লিনেন্ট যুক্ত করুন।

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.9</version>
</dependency>

HttpComponentsClientHttpRequestFactoryরেস্টটেম্পলেটটির জন্য অনুরোধ কারখানা হিসাবে ব্যবহার করুন । এটি করার সহজ উপায় হ'ল:

RestTemplate restTemplate = new RestTemplate();

restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory());

আপনার application.propertiesফাইলে DEBUG সক্ষম করুন (যদি আপনি স্প্রিং বুট ব্যবহার করছেন)

logging.level.org.apache.http=DEBUG

যদি আপনি স্প্রিং বুট ব্যবহার করছেন তবে আপনার অবশ্যই একটি লগিং ফ্রেমওয়ার্ক সেট আপ করা দরকার, যেমন একটি স্প্রিং-বুট-স্টার্টার নির্ভরতা ব্যবহার করে spring-boot-starter-logging

3. একটি ইন্টারসেপ্টর ব্যবহার করুন

আমি আপনাকে অন্যান্য উত্তর এবং মন্তব্যে প্রস্তাবগুলি, পাল্টা প্রস্তাবগুলি, এবং গেটচগুলি পড়তে দেব এবং আপনি যদি সেই পথে যেতে চান তবে নিজের জন্য সিদ্ধান্ত নেব।

4. দেহ ছাড়া URL এবং প্রতিক্রিয়া স্থিতিতে লগ করুন

যদিও এটি শরীরের লগিংয়ের বর্ণিত প্রয়োজনীয়তাগুলি পূরণ করে না, এটি আপনার আরএসটি কলগুলিতে লগ করা শুরু করার একটি দ্রুত এবং সহজ উপায়। এটি সম্পূর্ণ URL এবং প্রতিক্রিয়া স্থিতি প্রদর্শন করে।

কেবল আপনার application.propertiesফাইলে নিম্নলিখিত লাইনটি যুক্ত করুন (ধরে নিই যে আপনি স্প্রিং বুট ব্যবহার করছেন এবং ধরে নিচ্ছেন যে আপনি একটি স্প্রিং বুট স্টার্টার নির্ভরতা ব্যবহার করছেন spring-boot-starter-logging)

logging.level.org.springframework.web.client.RestTemplate = ডিবাগ

আউটপুটটি এরকম কিছু দেখবে:

2019-07-29 11:53:50.265 DEBUG o.s.web.client.RestTemplate : HTTP GET http://www.myrestservice.com/Endpoint?myQueryParam=myValue
2019-07-29 11:53:50.276 DEBUG o.s.web.client.RestTemplate : Accept=[application/json]
2019-07-29 11:53:50.584 DEBUG o.s.web.client.RestTemplate : Response 200 OK
2019-07-29 11:53:50.585 DEBUG o.s.web.client.RestTemplate : Reading to [org.mynamespace.MyJsonModelClass]

2
4 নং ডিবাগ করার সহজতম উপায়।
যুবরাজ

1
2 নং আমার জন্য কাজ করেছে। এটি অনুরোধ মূল অংশ লগ। ধন্যবাদ!
ক্যাগলার

1
আমি এই নম্বরে আসার পরে 3 নং এটি করার একটি সহজ উপায় পেয়েছি।
বিল নায়লার

12

অন্যান্য উত্তরে বর্ণিত এইচটিটিপিপ্লিয়েন্ট লগিংয়ের পাশাপাশি , আপনি একটি ক্লায়েন্টহট্টপ্রেইকুয়েস্টইন্টারসেপ্টারও প্রবর্তন করতে পারেন যা অনুরোধের প্রতিক্রিয়া এবং প্রতিক্রিয়াটি পড়ে এবং লগ করে। আপনি যদি এটি করতে চাইলে অন্য জিনিসগুলিও এইচটিপিপ্লিয়েন্ট ব্যবহার করে বা আপনি যদি কাস্টম লগিং বিন্যাস চান। সাবধানতা: আপনি রেস্টটেম্পলেটটিকে একটি বাফারিংক্লিনএইচটিপিআরকুয়েস্টফ্যাক্টির এমনটি দিতে চাইবেন যাতে আপনি দু'বার প্রতিক্রিয়াটি পড়তে পারেন।


12

অন্যান্য প্রতিক্রিয়াগুলিতে যেমন বলা হয়েছে, প্রতিক্রিয়া বডির বিশেষ চিকিত্সা প্রয়োজন যাতে এটি বারবার পড়তে পারে (ডিফল্টরূপে, এর সামগ্রীগুলি প্রথম পঠনের সময় গ্রাস হয়ে যায়)।

BufferingClientHttpRequestFactoryঅনুরোধটি সেট আপ করার সময় , ব্যবহার করার পরিবর্তে , ইন্টারসেপ্টর নিজেই প্রতিক্রিয়াটি গুটিয়ে রাখতে পারে এবং নিশ্চিত করতে পারে যে সামগ্রীটি বজায় রয়েছে এবং বারবার পড়তে পারে (লগারের পাশাপাশি প্রতিক্রিয়া গ্রাহক দ্বারা):

আমার বাধা, যা

  • একটি মোড়ক ব্যবহার করে প্রতিক্রিয়া বডি বাফার করে
  • আরও কমপ্যাক্ট উপায়ে লগ
  • স্থিতি কোড শনাক্তকারীকেও লগ করে (যেমন 201 তৈরি করা হয়েছে)
  • একাধিক থ্রেড থেকে সমবর্তী লগ এন্ট্রি সহজেই পৃথক করতে দেয় এমন একটি অনুরোধ ক্রম সংখ্যা অন্তর্ভুক্ত করে

কোড:

public class LoggingInterceptor implements ClientHttpRequestInterceptor {

    private final Logger log = LoggerFactory.getLogger(getClass());
    private AtomicInteger requestNumberSequence = new AtomicInteger(0);

    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        int requestNumber = requestNumberSequence.incrementAndGet();
        logRequest(requestNumber, request, body);
        ClientHttpResponse response = execution.execute(request, body);
        response = new BufferedClientHttpResponse(response);
        logResponse(requestNumber, response);
        return response;
    }

    private void logRequest(int requestNumber, HttpRequest request, byte[] body) {
        if (log.isDebugEnabled()) {
            String prefix = requestNumber + " > ";
            log.debug("{} Request: {} {}", prefix, request.getMethod(), request.getURI());
            log.debug("{} Headers: {}", prefix, request.getHeaders());
            if (body.length > 0) {
                log.debug("{} Body: \n{}", prefix, new String(body, StandardCharsets.UTF_8));
            }
        }
    }

    private void logResponse(int requestNumber, ClientHttpResponse response) throws IOException {
        if (log.isDebugEnabled()) {
            String prefix = requestNumber + " < ";
            log.debug("{} Response: {} {} {}", prefix, response.getStatusCode(), response.getStatusCode().name(), response.getStatusText());
            log.debug("{} Headers: {}", prefix, response.getHeaders());
            String body = StreamUtils.copyToString(response.getBody(), StandardCharsets.UTF_8);
            if (body.length() > 0) {
                log.debug("{} Body: \n{}", prefix, body);
            }
        }
    }

    /**
     * Wrapper around ClientHttpResponse, buffers the body so it can be read repeatedly (for logging & consuming the result).
     */
    private static class BufferedClientHttpResponse implements ClientHttpResponse {

        private final ClientHttpResponse response;
        private byte[] body;

        public BufferedClientHttpResponse(ClientHttpResponse response) {
            this.response = response;
        }

        @Override
        public HttpStatus getStatusCode() throws IOException {
            return response.getStatusCode();
        }

        @Override
        public int getRawStatusCode() throws IOException {
            return response.getRawStatusCode();
        }

        @Override
        public String getStatusText() throws IOException {
            return response.getStatusText();
        }

        @Override
        public void close() {
            response.close();
        }

        @Override
        public InputStream getBody() throws IOException {
            if (body == null) {
                body = StreamUtils.copyToByteArray(response.getBody());
            }
            return new ByteArrayInputStream(body);
        }

        @Override
        public HttpHeaders getHeaders() {
            return response.getHeaders();
        }
    }
}

কনফিগারেশন:

 @Bean
    public RestTemplateBuilder restTemplateBuilder() {
        return new RestTemplateBuilder()
                .additionalInterceptors(Collections.singletonList(new LoggingInterceptor()));
    }

লগ আউটপুট উদাহরণ:

2018-10-08 10:58:53 [main] DEBUG x.y.z.LoggingInterceptor - 2 >  Request: POST http://localhost:53969/payment/v4/private/payment-lists/10022/templates
2018-10-08 10:58:53 [main] DEBUG x.y.z.LoggingInterceptor - 2 >  Headers: {Accept=[application/json, application/json], Content-Type=[application/json;charset=UTF-8], Content-Length=[986]}
2018-10-08 10:58:53 [main] DEBUG x.y.z.LoggingInterceptor - 2 >  Body: 
{"idKey":null, ...}
2018-10-08 10:58:53 [main] DEBUG x.y.z.LoggingInterceptor - 2 <  Response: 200 OK 
2018-10-08 10:58:53 [main] DEBUG x.y.z.LoggingInterceptor - 2 <  Headers: {Content-Type=[application/json;charset=UTF-8], Transfer-Encoding=[chunked], Date=[Mon, 08 Oct 2018 08:58:53 GMT]}
2018-10-08 10:58:53 [main] DEBUG x.y.z.LoggingInterceptor - 2 <  Body: 
{ "idKey" : "10022", ...  }

1
এটি শরীরের অক্ষত রেখে 2019 সালের বসন্ত সংস্করণে কাজ করে।
উদো 2

1
স্প্রিং 2.1.10 এ কাজ করে :) ধন্যবাদ
মোলার


8

এটি করার সঠিক উপায় নাও হতে পারে তবে আমি মনে করি লগগুলিতে খুব বেশি পূরণ না করেই অনুরোধ এবং প্রতিক্রিয়াগুলি মুদ্রণের জন্য এটি সবচেয়ে সহজ পদ্ধতি।

2 লাইনের নীচে যুক্ত করে অ্যাপ্লিকেশন.প্রাপ্তি সমস্ত অনুরোধ এবং প্রতিক্রিয়া লগ করে অনুরোধগুলি লগ করার জন্য প্রথম লাইন এবং প্রতিক্রিয়াগুলিতে লগ করার জন্য ২ য় লাইন।

logging.level.org.springframework.web.client.RestTemplate=DEBUG
logging.level.org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor=DEBUG

প্রতিক্রিয়া লগ করা আমার পক্ষে কাজ করে না। এটি কেবল স্থিতি কোডে লগ করে। এটি পেডলোড লগ করা উচিত?
badera

ক্লাস এইচটিপিএনটিটিমিথডপ্রসেসর (v5.1.8) কিছুই লগ করেন না।
ক্রিস

6

ধরে নিচ্ছি এইচটিপিপিলেয়েন্ট ৪.x ব্যবহারের RestTemplateজন্য কনফিগার করা হয়েছে, আপনি এখানে এইচটিটিপি ক্লায়েন্টের লগিং ডকুমেন্টেশন পড়তে পারেন । অন্যান্য উত্তরগুলিতে বর্ণিতদের চেয়ে লগারগুলি আলাদা।

HTTPClient 3.x এর জন্য লগিং কনফিগারেশনটি এখানে উপলব্ধ ।


4

এখানে অনেক প্রতিক্রিয়ার কোডিং পরিবর্তন এবং কাস্টমাইজড ক্লাস প্রয়োজন এবং এটি সত্যই প্রয়োজন হয় না। ফিডলারের মতো একটি ডিবাগিং প্রক্সি পান এবং কমান্ড লাইনে (-Dhttp.proxyHost এবং -Dhttp.proxyPort) প্রক্সিটি ব্যবহার করার জন্য আপনার জাভা পরিবেশ সেট করুন তারপরে ফিজারটি চালান এবং আপনি অনুরোধ এবং প্রতিক্রিয়াগুলি তাদের সম্পূর্ণতার মধ্যে দেখতে পারেন। এছাড়াও অনেকগুলি আনুষঙ্গিক সুবিধাগুলি যেমন সার্ভার সংশোধন করার প্রতিশ্রুতি দেওয়ার আগে পরীক্ষাগুলি চালানোর জন্য প্রেরণ করার আগে এবং পরে ফলাফল এবং প্রতিক্রিয়াগুলির সাথে টিঙ্কার করার ক্ষমতা নিয়ে আসে।

শেষ হতে পারে এমন একটি ইস্যুটি যদি আপনাকে এইচটিটিপিএস ব্যবহার করতে হয় তবে আপনাকে ফিডলারের কাছ থেকে এসএসএল শংসাপত্রটি রফতানি করতে হবে এবং এটি জাভা কীস্টোর (ক্যাচার্টস) ইঙ্গিতটিতে আমদানি করতে হবে: ডিফল্ট জাভা কীস্টোর পাসওয়ার্ডটি সাধারণত "পরিবর্তন" হয়।


1
এটি আমার জন্য ইন্টিলিজ এবং ফিডলের নিয়মিত ইনস্টল ব্যবহার করে কাজ করেছিল। আমি রান কনফিগারেশন সম্পাদনা করেছি এবং এতে ভিএম বিকল্পগুলি সেট করেছি -DproxySet=true -Dhttp.proxyHost=localhost -Dhttp.proxyPort=8888
জেডি

ধন্যবাদ! এটি আপনার নিজের ইন্টারসেপ্টর লেখার তুলনায় একটি দুর্দান্ত মার্জিত সমাধান।
ক্রিস

3

অ্যাপাচি এইচটিটিপিপ্লায়েন্টের সহায়তায় লগব্যাকটিতে লগ করার জন্য :

আপনার ক্লাসপথে অ্যাপাচি এইচটিপিপিলেট দরকার:

<dependency>
  <groupId>org.apache.httpcomponents</groupId>
  <artifactId>httpclient</artifactId>
  <version>4.5.10</version>
</dependency>

আপনার RestTemplateএইচটিপিপিলেট ব্যবহার করতে কনফিগার করুন :

restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory());

অনুরোধ এবং প্রতিক্রিয়াগুলি লগ করতে লগব্যাক কনফিগারেশন ফাইলটিতে যুক্ত করুন:

<logger name="org.apache.http.wire" level="DEBUG"/>

অথবা আরও লগ ইন:

<logger name="org.apache.http" level="DEBUG"/>

কোন লগব্যাক কনফিগারেশন ফাইল?
জি_ভি

1
পরীক্ষার জন্য @ জি_ভি লগব্যাক.এক্সএমএল বা লগব্যাক-টেস্ট.এক্সএমএল।
holmis83

এটি org.apache.http.wire=DEBUGআপনার application.propertiesএখনকার সাথেও কাজ করে
G_V

আপনি যদি স্প্রিং-বুট ব্যবহার করেন তবে @G_V। আমার উত্তর বুট ছাড়াই কাজ করে।
holmis83

2

আপনার কনফিগার করার কৌতুক RestTemplateএকটি সঙ্গে BufferingClientHttpRequestFactoryযদি আপনি কোন ব্যবহার করছেন কিনা তা কাজ করে না ClientHttpRequestInterceptor, যা আপনি হবে যদি আপনি interceptors খুব মাধ্যমে লগ ইন করার চেষ্টা করছেন। এটি যে পদ্ধতিতে কাজ করে InterceptingHttpAccessor(যা RestTemplateসাবক্লাসগুলি) এর কারণে এটি ।

দীর্ঘ গল্প সংক্ষিপ্ত ... কেবলমাত্র এই শ্রেণীর জায়গায় RestTemplateব্যবহার করুন (এটি SLF4J লগিং এপিআই ব্যবহার করে নোট করুন, প্রয়োজন অনুসারে সম্পাদনা করুন):

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpRequest;
import org.springframework.http.HttpStatus;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.web.client.RestTemplate;

/**
 * A {@link RestTemplate} that logs every request and response.
 */
public class LoggingRestTemplate extends RestTemplate {

    // Bleh, this class is not public
    private static final String RESPONSE_WRAPPER_CLASS = "org.springframework.http.client.BufferingClientHttpResponseWrapper";

    private Logger log = LoggerFactory.getLogger(this.getClass());

    private boolean hideAuthorizationHeaders = true;
    private Class<?> wrapperClass;
    private Constructor<?> wrapperConstructor;

    /**
     * Configure the logger to log requests and responses to.
     *
     * @param log log destination, or null to disable
     */
    public void setLogger(Logger log) {
        this.log = log;
    }

    /**
     * Configure the logger to log requests and responses to by name.
     *
     * @param name name of the log destination, or null to disable
     */
    public void setLoggerName(String name) {
        this.setLogger(name != null ? LoggerFactory.getLogger(name) : null);
    }

    /**
     * Configure whether to hide the contents of {@code Authorization} headers.
     *
     * <p>
     * Default true.
     *
     * @param hideAuthorizationHeaders true to hide, otherwise false
     */
    public void setHideAuthorizationHeaders(boolean hideAuthorizationHeaders) {
        this.hideAuthorizationHeaders = hideAuthorizationHeaders;
    }

    /**
     * Log a request.
     */
    protected void traceRequest(HttpRequest request, byte[] body) {
        this.log.debug("xmit: {} {}\n{}{}", request.getMethod(), request.getURI(), this.toString(request.getHeaders()),
          body != null && body.length > 0 ? "\n\n" + new String(body, StandardCharsets.UTF_8) : "");
    }

    /**
     * Log a response.
     */
    protected void traceResponse(ClientHttpResponse response) {
        final ByteArrayOutputStream bodyBuf = new ByteArrayOutputStream();
        HttpStatus statusCode = null;
        try {
            statusCode = response.getStatusCode();
        } catch (IOException e) {
            // ignore
        }
        String statusText = null;
        try {
            statusText = response.getStatusText();
        } catch (IOException e) {
            // ignore
        }
        try (final InputStream input = response.getBody()) {
            byte[] b = new byte[1024];
            int r;
            while ((r = input.read(b)) != -1)
                bodyBuf.write(b, 0, r);
        } catch (IOException e) {
            // ignore
        }
        this.log.debug("recv: {} {}\n{}{}", statusCode, statusText, this.toString(response.getHeaders()),
          bodyBuf.size() > 0 ? "\n\n" + new String(bodyBuf.toByteArray(), StandardCharsets.UTF_8) : "");
    }

    @PostConstruct
    private void addLoggingInterceptor() {
        this.getInterceptors().add(new ClientHttpRequestInterceptor() {
            @Override
            public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution)
              throws IOException {

                // Log request
                if (LoggingRestTemplate.this.log != null && LoggingRestTemplate.this.log.isDebugEnabled())
                    LoggingRestTemplate.this.traceRequest(request, body);

                // Perform request
                ClientHttpResponse response = execution.execute(request, body);

                // Log response
                if (LoggingRestTemplate.this.log != null && LoggingRestTemplate.this.log.isDebugEnabled()) {
                    final ClientHttpResponse bufferedResponse = LoggingRestTemplate.this.ensureBuffered(response);
                    if (bufferedResponse != null) {
                        LoggingRestTemplate.this.traceResponse(bufferedResponse);
                        response = bufferedResponse;
                    }
                }

                // Done
                return response;
            }
        });
    }

    private ClientHttpResponse ensureBuffered(ClientHttpResponse response) {
        try {
            if (this.wrapperClass == null)
                this.wrapperClass = Class.forName(RESPONSE_WRAPPER_CLASS, false, ClientHttpResponse.class.getClassLoader());
            if (!this.wrapperClass.isInstance(response)) {
                if (this.wrapperConstructor == null) {
                    this.wrapperConstructor = this.wrapperClass.getDeclaredConstructor(ClientHttpResponse.class);
                    this.wrapperConstructor.setAccessible(true);
                }
                response = (ClientHttpResponse)this.wrapperConstructor.newInstance(response);
            }
            return response;
        } catch (Exception e) {
            this.log.error("error creating {} instance: {}", RESPONSE_WRAPPER_CLASS, e);
            return null;
        }
    }

    private String toString(HttpHeaders headers) {
        final StringBuilder headerBuf = new StringBuilder();
        for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
            if (headerBuf.length() > 0)
                headerBuf.append('\n');
            final String name = entry.getKey();
            for (String value : entry.getValue()) {
                if (this.hideAuthorizationHeaders && name.equalsIgnoreCase(HttpHeaders.AUTHORIZATION))
                    value = "[omitted]";
                headerBuf.append(name).append(": ").append(value);
            }
        }
        return headerBuf.toString();
    }
}

আমি একমত যে এটি নির্বোধ যে এটি করার জন্য এটি এত বেশি কাজ করে।


2

উপরোক্ত আলোচনায় যুক্ত করা এটি কেবল শুভ দৃশ্যের প্রতিনিধিত্ব করে। সম্ভবত কোনও ত্রুটি এলে আপনি প্রতিক্রিয়াটি লগ করতে সক্ষম হবেন না ।

এই ক্ষেত্রে প্লাসের উপরের সমস্ত ক্ষেত্রে আপনার অবশ্যই ডিফল্ট রিসপনসইররহ্যান্ডলারকে ওভাররাইড করতে হবে এবং নীচের মত সেট করতে হবে

restTemplate.setErrorHandler(new DefaultResponseErrorHandlerImpl());

2

আশ্চর্যের বিষয় হল, এই সমাধানগুলির কোনওটিই রেস্টস্টেম্পলেট হিসাবে কাজ করে না বলে মনে হয় যে কিছু ক্লায়েন্ট এবং সার্ভার 500x ত্রুটির প্রতিক্রিয়া ফিরিয়ে দিয়েছে। যে ক্ষেত্রে, আপনি নিম্নরূপভাবে রেসপন্সেরররহ্যান্ডলার প্রয়োগ করে তাদের লগ করতে পারেন। এখানে একটি খসড়া কোড রয়েছে তবে আপনি পয়েন্টটি পাবেন:

আপনি ত্রুটি হ্যান্ডলার হিসাবে একই ইন্টারসেপ্টার সেট করতে পারেন:

restTemplate.getInterceptors().add(interceptor);
restTemplate.setRequestFactory(new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory()));
restTemplate.setErrorHandler(interceptor);

এবং ইন্টারসেপ্ট উভয় ইন্টারফেস প্রয়োগ করে:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashSet;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpRequest;
import org.springframework.http.HttpStatus.Series;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.web.client.DefaultResponseErrorHandler;
import org.springframework.web.client.ResponseErrorHandler;

public class LoggingRequestInterceptor implements ClientHttpRequestInterceptor, ResponseErrorHandler {
    static final Logger log = LoggerFactory.getLogger(LoggingRequestInterceptor.class);
    static final DefaultResponseErrorHandler defaultResponseErrorHandler = new DefaultResponseErrorHandler();
    final Set<Series> loggableStatuses = new HashSet();

    public LoggingRequestInterceptor() {
    }

    public LoggingRequestInterceptor(Set<Series> loggableStatuses) {
        loggableStatuses.addAll(loggableStatuses);
    }

    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        this.traceRequest(request, body);
        ClientHttpResponse response = execution.execute(request, body);
        if(response != null) {
            this.traceResponse(response);
        }

        return response;
    }

    private void traceRequest(HttpRequest request, byte[] body) throws IOException {
        log.debug("===========================request begin================================================");
        log.debug("URI         : {}", request.getURI());
        log.debug("Method      : {}", request.getMethod());
        log.debug("Headers     : {}", request.getHeaders());
        log.debug("Request body: {}", new String(body, "UTF-8"));
        log.debug("==========================request end================================================");
    }

    private void traceResponse(ClientHttpResponse response) throws IOException {
        if(this.loggableStatuses.isEmpty() || this.loggableStatuses.contains(response.getStatusCode().series())) {
            StringBuilder inputStringBuilder = new StringBuilder();

            try {
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(response.getBody(), "UTF-8"));

                for(String line = bufferedReader.readLine(); line != null; line = bufferedReader.readLine()) {
                    inputStringBuilder.append(line);
                    inputStringBuilder.append('\n');
                }
            } catch (Throwable var5) {
                log.error("cannot read response due to error", var5);
            }

            log.debug("============================response begin==========================================");
            log.debug("Status code  : {}", response.getStatusCode());
            log.debug("Status text  : {}", response.getStatusText());
            log.debug("Headers      : {}", response.getHeaders());
            log.debug("Response body: {}", inputStringBuilder.toString());
            log.debug("=======================response end=================================================");
        }

    }

    public boolean hasError(ClientHttpResponse response) throws IOException {
        return defaultResponseErrorHandler.hasError(response);
    }

    public void handleError(ClientHttpResponse response) throws IOException {
        this.traceResponse(response);
        defaultResponseErrorHandler.handleError(response);
    }
}

বডি যদি মাল্টিপার্ট / ফর্ম-ডেটা হয় তবে লগ থেকে বাইনারি ডেটা (ফাইলের সামগ্রী) ফিল্টার আউট করার কোন সহজ উপায় আছে?
লুক

1

@ মিলাচএইচ-তে নির্দেশিত হিসাবে, প্রয়োগে একটি ত্রুটি রয়েছে। যদি কোনও স্ট্যাটাস কোড> 400 ফিরিয়ে দেওয়া হয় তবে আইওএক্সেপশনটি নিক্ষেপ করা হয়, কারণ ত্রুটিহ্যান্ডলারটি ইন্টারসেপ্টারদের দ্বারা না ডাকা হয়। ব্যতিক্রম উপেক্ষা করা যায় এবং হ্যান্ডলার পদ্ধতিতে আবার ধরা পড়ে।

package net.sprd.fulfillment.common;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import static java.nio.charset.StandardCharsets.UTF_8;

public class LoggingRequestInterceptor implements ClientHttpRequestInterceptor {

    final static Logger log = LoggerFactory.getLogger(LoggingRequestInterceptor.class);

    @SuppressWarnings("HardcodedLineSeparator")
    public static final char LINE_BREAK = '\n';

    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        try {
            traceRequest(request, body);
        } catch (Exception e) {
            log.warn("Exception in LoggingRequestInterceptor while tracing request", e);
        }

        ClientHttpResponse response = execution.execute(request, body);

        try {
            traceResponse(response);
        } catch (IOException e) {
            // ignore the exception here, as it will be handled by the error handler of the restTemplate
            log.warn("Exception in LoggingRequestInterceptor", e);
        }
        return response;
    }

    private void traceRequest(HttpRequest request, byte[] body) {
        log.info("===========================request begin================================================");
        log.info("URI         : {}", request.getURI());
        log.info("Method      : {}", request.getMethod());
        log.info("Headers     : {}", request.getHeaders());
        log.info("Request body: {}", new String(body, UTF_8));
        log.info("==========================request end================================================");
    }

    private void traceResponse(ClientHttpResponse response) throws IOException {
        StringBuilder inputStringBuilder = new StringBuilder();
        try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(response.getBody(), UTF_8))) {
            String line = bufferedReader.readLine();
            while (line != null) {
                inputStringBuilder.append(line);
                inputStringBuilder.append(LINE_BREAK);
                line = bufferedReader.readLine();
            }
        }

        log.info("============================response begin==========================================");
        log.info("Status code  : {}", response.getStatusCode());
        log.info("Status text  : {}", response.getStatusText());
        log.info("Headers      : {}", response.getHeaders());
        log.info("Response body: {}", inputStringBuilder);
        log.info("=======================response end=================================================");
    }

}

0

এখন সেরা সমাধান, কেবল নির্ভরতা যুক্ত করুন:

<dependency>
  <groupId>com.github.zg2pro</groupId>
  <artifactId>spring-rest-basis</artifactId>
  <version>v.x</version>
</dependency>

এটিতে একটি লগিং-রেকর্ডআইন্টারসেপ্টর শ্রেণি রয়েছে যা আপনি নিজের রেস্টটেম্পলেটে সেইভাবে যুক্ত করতে পারেন:

নীচের পদ্ধতিতে একটি স্প্রিং রেস্টটেম্পলেটটিতে একটি ইন্টারসেপ্টর হিসাবে যুক্ত করে এই ইউটিলিটিটি সংহত করুন:

restTemplate.setRequestFactory(LoggingRequestFactoryFactory.build());

এবং log4j এর মতো আপনার কাঠামোয় একটি slf4j বাস্তবায়ন যুক্ত করুন।

বা সরাসরি "Zg2proRestTemplate" ব্যবহার করুন । @ পলস্যাবউয়ের "সেরা উত্তর "টি তেমন দেখাচ্ছে, যেহেতু একটি স্প্রিং রেস্টটেম্পলেট ব্যবহার করার সময় httpclient এবং সমস্ত apache.htp libs অগত্যা লোড করা হয় না।


প্রকাশিত সংস্করণটি কী?
পোপালকা

প্রকাশিত সংস্করণটি এখন 0.2
মূসা মায়ার

1
ব্যবহারের সহজতা দুর্দান্ত, তবে এতে শিরোনামের অভাব রয়েছে
WrRaThY

অতিরিক্তভাবে: লগিংআরকিউস্টইন্টারসেপ্টারে সমস্ত দরকারী পদ্ধতিগুলি ব্যক্তিগত, এটি যখন সম্প্রসারণের ক্ষেত্রে আসে তখন এটি একটি সমস্যা (সুরক্ষিত হতে পারে)
WrRaThY

দুঃখের বিষয়, আমি 5 মিনিটের পরে মন্তব্যগুলি সম্পাদনা করতে পারি না। হেডারে লগ করতে আপনাকে যা করতে হবে তা হ'ল: log("Headers: {}", request.headers)ইন LoggingRequestInterceptor:traceRequestএবং log("Headers: {}", response.headers)ইন LoggingRequestInterceptor:logResponse। আপনি হেডিং এবং বডি লগিংয়ের জন্য কিছু পতাকা যুক্ত করার বিষয়ে ভাবতে চাইতে পারেন। এছাড়াও - আপনি লগিংয়ের জন্য বডি কনটেন্টের প্রকারটি পরীক্ষা করতে চাইতে পারেন (উদাহরণস্বরূপ কেবল অ্যাপ্লিকেশন / জেএসন * লগ করুন)। এটি কনফিগারযোগ্যও হওয়া উচিত। সব মিলিয়ে, এই ছোট্ট টুইটগুলির সাথে আপনার ছড়িয়ে পড়ার জন্য একটি দুর্দান্ত গ্রন্থাগার থাকবে। ভাল কাজ :)
WrRaThY

0

এটিও আমার বাস্তবায়ন যুক্ত করতে চেয়েছিল। সমস্ত অনুপস্থিত আধা-কলোনগুলির জন্য আমি ক্ষমাপ্রার্থী, এটি গ্রোভিতে লেখা।

আমার গৃহীত উত্তরগুলির চেয়ে আরও কিছু কনফিগার করার দরকার ছিল। এখানে একটি বিশ্রাম টেম্পলেট বিন রয়েছে যা খুব চটুল এবং ওপি যেমন সন্ধান করছে তার মতো সবকিছু লগ করবে।

কাস্টম লগিং ইন্টারসেপ্টর শ্রেণি:

import org.springframework.http.HttpRequest
import org.springframework.http.client.ClientHttpRequestExecution
import org.springframework.http.client.ClientHttpRequestInterceptor
import org.springframework.http.client.ClientHttpResponse
import org.springframework.util.StreamUtils

import java.nio.charset.Charset

class HttpLoggingInterceptor implements ClientHttpRequestInterceptor {

    private final static Logger log = LoggerFactory.getLogger(HttpLoggingInterceptor.class)

    @Override
    ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        logRequest(request, body)
        ClientHttpResponse response = execution.execute(request, body)
        logResponse(response)
        return response
    }

    private void logRequest(HttpRequest request, byte[] body) throws IOException {
        if (log.isDebugEnabled()) {
            log.debug("===========================request begin================================================")
            log.debug("URI         : {}", request.getURI())
            log.debug("Method      : {}", request.getMethod())
            log.debug("Headers     : {}", request.getHeaders())
            log.debug("Request body: {}", new String(body, "UTF-8"))
            log.debug("==========================request end================================================")
        }
    }

    private void logResponse(ClientHttpResponse response) throws IOException {
        if (log.isDebugEnabled()) {
            log.debug("============================response begin==========================================")
            log.debug("Status code  : {}", response.getStatusCode())
            log.debug("Status text  : {}", response.getStatusText())
            log.debug("Headers      : {}", response.getHeaders())
            log.debug("Response body: {}", StreamUtils.copyToString(response.getBody(), Charset.defaultCharset()))
            log.debug("=======================response end=================================================")
        }
    }
}

বিশ্রাম টেম্পলেট শিম সংজ্ঞা:

@Bean(name = 'myRestTemplate')
RestTemplate myRestTemplate(RestTemplateBuilder builder) {

    RequestConfig requestConfig = RequestConfig.custom()
            .setConnectTimeout(10 * 1000) // 10 seconds
            .setSocketTimeout(300 * 1000) // 300 seconds
            .build()

    PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager()
    connectionManager.setMaxTotal(10)
    connectionManager.closeIdleConnections(5, TimeUnit.MINUTES)

    CloseableHttpClient httpClient = HttpClients.custom()
            .setConnectionManager(connectionManager)
            .setDefaultRequestConfig(requestConfig)
            .disableRedirectHandling()
            .build()

    RestTemplate restTemplate = builder
            .rootUri("https://domain.server.com")
            .basicAuthorization("username", "password")
            .requestFactory(new BufferingClientHttpRequestFactory(new HttpComponentsClientHttpRequestFactory(httpClient)))
            .interceptors(new HttpLoggingInterceptor())
            .build()

    return restTemplate
}

বাস্তবায়ন:

@Component
class RestService {

    private final RestTemplate restTemplate
    private final static Logger log = LoggerFactory.getLogger(RestService.class)

    @Autowired
    RestService(
            @Qualifier("myRestTemplate") RestTemplate restTemplate
    ) {
        this.restTemplate = restTemplate
    }

    // add specific methods to your service that access the GET and PUT methods

    private <T> T getForObject(String path, Class<T> object, Map<String, ?> params = [:]) {
        try {
            return restTemplate.getForObject(path, object, params)
        } catch (HttpClientErrorException e) {
            log.warn("Client Error (${path}): ${e.responseBodyAsString}")
        } catch (HttpServerErrorException e) {
            String msg = "Server Error (${path}): ${e.responseBodyAsString}"
            log.error(msg, e)
        } catch (RestClientException e) {
            String msg = "Error (${path})"
            log.error(msg, e)
        }
        return null
    }

    private <T> T putForObject(String path, T object) {
        try {
            HttpEntity<T> request = new HttpEntity<>(object)
            HttpEntity<T> response = restTemplate.exchange(path, HttpMethod.PUT, request, T)
            return response.getBody()
        } catch (HttpClientErrorException e) {
            log.warn("Error (${path}): ${e.responseBodyAsString}")
        } catch (HttpServerErrorException e) {
            String msg = "Error (${path}): ${e.responseBodyAsString}"
            log.error(msg, e)
        } catch (RestClientException e) {
            String msg = "Error (${path})"
            log.error(msg, e)
        }
        return null
    }
}

0

অনুরোধটি লগ করার জন্য প্রশ্ন / এ পড়ুন এবং এইচটিপিপিপুট স্ট্রিমে একাধিক পাঠ সক্ষম করে বাকী টেম্পলেটটির জন্য প্রতিক্রিয়া জানান

কেন আমার কাস্টম ক্লায়েন্ট HTTPRequestIntercepter খালি প্রতিক্রিয়া সঙ্গে


0

org.apache.http.wire দিতে খুব অপাঠ্য লগ, তাই আমি ব্যবহার logbook লগ ইন করার আবেদন সার্ভলেট এবং RestTemplate req / রেস্প লগে

build.gradle

compile group: 'org.zalando', name: 'logbook-spring-boot-starter', version: '1.13.0'

application.properties

logging.level.org.zalando.logbook:TRACE

RestTemplate

@Configuration
public class RestTemplateConfig {

@Autowired
private LogbookHttpRequestInterceptor logbookHttpRequestInterceptor;

@Autowired
private LogbookHttpResponseInterceptor logbookHttpResponseInterceptor;

@Bean
public RestTemplate restTemplate() {
    return new RestTemplateBuilder()
        .requestFactory(new MyRequestFactorySupplier())
        .build();
}

class MyRequestFactorySupplier implements Supplier<ClientHttpRequestFactory> {

    @Override
    public ClientHttpRequestFactory get() {
        // Using Apache HTTP client.
        CloseableHttpClient client = HttpClientBuilder.create()
            .addInterceptorFirst(logbookHttpRequestInterceptor)
            .addInterceptorFirst(logbookHttpResponseInterceptor)
            .build();
        HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(client);
        return clientHttpRequestFactory;
    }

}
}

-1

ক্লায়েন্টহট্টপিন্টারসেপ্টর ব্যবহার করে প্রতিক্রিয়া সম্পর্কিত, আমি বাফারিং কারখানাগুলি ছাড়াই পুরো প্রতিক্রিয়া রাখার একটি উপায় খুঁজে পেয়েছি। কেবলমাত্র কিছু ব্যবহার পদ্ধতি ব্যবহার করে বাইট অ্যারের অভ্যন্তরে প্রতিক্রিয়ার বডি ইনপুট স্ট্রিমটি সংরক্ষণ করুন যা এই অ্যারেটি শরীর থেকে অনুলিপি করবে, তবে গুরুত্বপূর্ণ, এই পদ্ধতিটিকে চারপাশে ঘিরে ফেলুন কারণ প্রতিক্রিয়া ফাঁকা থাকলে তা ভেঙে যাবে (এটি রিসোর্স অ্যাক্সেস ব্যতিক্রমের কারণ) এবং ক্যাচ খালি খালি বাইট অ্যারে তৈরি করুন এবং ক্লায়েন্টহট্টপ্রেস্পোনসের বেনামে অভ্যন্তর শ্রেণীর তৈরি না করে মূল প্রতিক্রিয়া থেকে অ্যারে এবং অন্যান্য পরামিতিগুলি ব্যবহার করে। আপনি যে নতুন ক্লায়েন্ট এইচটিপিআরএস ফোনটি টেমপ্লেট এক্সিকিউশন শৃঙ্খলে ফিরিয়ে দিতে পারবেন এবং আপনি পূর্বে সঞ্চিত বডি বাইট অ্যারে ব্যবহার করে প্রতিক্রিয়া লগ করতে পারেন। আপনি প্রকৃত প্রতিক্রিয়াতে ইনপুট স্ট্রিম গ্রহণ করা এড়াতে পারবেন এবং আপনি রেস্ট টেম্পলেট প্রতিক্রিয়াটি যেমনটি ব্যবহার করতে পারেন। বিঃদ্রঃ,


-2

আমার লগার কনফিগার এক্সএমএল ব্যবহৃত হয়েছে

<logger name="org.springframework.web.client.RestTemplate">
    <level value="trace"/>
</logger>

তাহলে আপনি নীচের মতো কিছু পাবেন:

DEBUG org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:92) : Reading [com.test.java.MyClass] as "application/json" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@604525f1]

HTTPMessageConverterExtractor.java:92 এর মাধ্যমে আপনার ডিবাগ চালিয়ে যাওয়া দরকার, এবং আমার ক্ষেত্রে, আমি এটি পেয়েছি:

genericMessageConverter.write(requestBody, requestBodyType, requestContentType, httpRequest);

এবং এই:

outputMessage.getBody().flush();

আউটপুটমেসেজ.জেটবিডি () তে পোস্ট করা বার্তা (পোস্ট টাইপ) থাকে contains


ট্রেস লগিং খুব ভার্জোজ হতে পারে ... যদি প্রতি সেকেন্ডে কয়েক হাজার অনুরোধ থাকে ??
গার্ভাসিও অ্যামি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.