কোনও নেটওয়ার্ক প্রোটোকল ডিবাগিংয়ের জন্য স্ক্রিপ্ট বা এমনকি অ্যাপ্লিকেশনটির একটি সাবসিস্টেম থাকা, কার্যকর ইউআরএল, শিরোনাম, পে-লোড এবং স্থিতি সহ অনুরোধ-প্রতিক্রিয়া জুটিগুলি ঠিক কী তা দেখার জন্য এটি আকাঙ্ক্ষিত। এবং এটি পুরো জায়গা জুড়ে পৃথক অনুরোধের জন্য যন্ত্রটি অবৈধ। একই সময়ে কর্মক্ষমতা বিবেচনা রয়েছে যা একক (বা কয়েকটি বিশেষজ্ঞ) ব্যবহার করার পরামর্শ দেয়requests.Session
, সুতরাং নিম্নলিখিতটি অনুমান করা হয় যে পরামর্শটি অনুসরণ করা হয়েছে।
requests
তথাকথিত ইভেন্ট হুক সমর্থন করে (২.২৩ পর্যন্ত আসলে কেবল response
হুক রয়েছে)। এটি মূলত ইভেন্ট শ্রোতা এবং ইভেন্টটি নিয়ন্ত্রণ থেকে ফিরে আসার আগেই নির্গত হয় requests.request
। এই মুহুর্তে উভয় অনুরোধ এবং প্রতিক্রিয়া সম্পূর্ণরূপে সংজ্ঞায়িত করা হয়েছে, তাই লগ করা যায়।
import logging
import requests
logger = logging.getLogger('httplogger')
def logRoundtrip(response, *args, **kwargs):
extra = {'req': response.request, 'res': response}
logger.debug('HTTP roundtrip', extra=extra)
session = requests.Session()
session.hooks['response'].append(logRoundtrip)
এটি মূলত কোনও সেশনের সমস্ত এইচটিটিপি রাউন্ড-ট্রিপগুলিতে লগ করা যায়।
ফর্ম্যাট করা HTTP রাউন্ড-ট্রিপ লগ রেকর্ডগুলি
উপরের লগিংটি কার্যকর হওয়ার জন্য এখানে বিশেষায়িত লগিং ফর্ম্যাটর থাকতে পারে যা লগিং রেকর্ডগুলিতে বোঝে req
এবং res
অতিরিক্ত। এটি দেখতে এটি দেখতে পারেন:
import textwrap
class HttpFormatter(logging.Formatter):
def _formatHeaders(self, d):
return '\n'.join(f'{k}: {v}' for k, v in d.items())
def formatMessage(self, record):
result = super().formatMessage(record)
if record.name == 'httplogger':
result += textwrap.dedent('''
---------------- request ----------------
{req.method} {req.url}
{reqhdrs}
{req.body}
---------------- response ----------------
{res.status_code} {res.reason} {res.url}
{reshdrs}
{res.text}
''').format(
req=record.req,
res=record.res,
reqhdrs=self._formatHeaders(record.req.headers),
reshdrs=self._formatHeaders(record.res.headers),
)
return result
formatter = HttpFormatter('{asctime} {levelname} {name} {message}', style='{')
handler = logging.StreamHandler()
handler.setFormatter(formatter)
logging.basicConfig(level=logging.DEBUG, handlers=[handler])
এখন আপনি যদি কিছুগুলি অনুরোধ করে session
যেমন:
session.get('https://httpbin.org/user-agent')
session.get('https://httpbin.org/status/200')
আউটপুট নীচের মত দেখতে stderr
হবে।
2020-05-14 22:10:13,224 DEBUG urllib3.connectionpool Starting new HTTPS connection (1): httpbin.org:443
2020-05-14 22:10:13,695 DEBUG urllib3.connectionpool https://httpbin.org:443 "GET /user-agent HTTP/1.1" 200 45
2020-05-14 22:10:13,698 DEBUG httplogger HTTP roundtrip
---------------- request ----------------
GET https://httpbin.org/user-agent
User-Agent: python-requests/2.23.0
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive
None
---------------- response ----------------
200 OK https://httpbin.org/user-agent
Date: Thu, 14 May 2020 20:10:13 GMT
Content-Type: application/json
Content-Length: 45
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
{
"user-agent": "python-requests/2.23.0"
}
2020-05-14 22:10:13,814 DEBUG urllib3.connectionpool https://httpbin.org:443 "GET /status/200 HTTP/1.1" 200 0
2020-05-14 22:10:13,818 DEBUG httplogger HTTP roundtrip
---------------- request ----------------
GET https://httpbin.org/status/200
User-Agent: python-requests/2.23.0
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive
None
---------------- response ----------------
200 OK https://httpbin.org/status/200
Date: Thu, 14 May 2020 20:10:13 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 0
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
একটি জিইউআই উপায়
আপনার যখন অনেকগুলি প্রশ্ন থাকে, একটি সাধারণ ইউআই থাকে এবং রেকর্ডগুলি ফিল্টার করার একটি উপায় কার্যকর হয়। আমি তার জন্য ক্রোনোলগার ব্যবহার করতে দেখাব (যা আমি এর লেখক)।
প্রথমত, logging
তারটি প্রেরণ করার সময় হুককে রেকর্ড তৈরি করতে পুনরায় রচনা করা যেতে পারে যা সিরিয়ালিয়াস করতে পারে । এটি দেখতে এটি দেখতে পারেন:
def logRoundtrip(response, *args, **kwargs):
extra = {
'req': {
'method': response.request.method,
'url': response.request.url,
'headers': response.request.headers,
'body': response.request.body,
},
'res': {
'code': response.status_code,
'reason': response.reason,
'url': response.url,
'headers': response.headers,
'body': response.text
},
}
logger.debug('HTTP roundtrip', extra=extra)
session = requests.Session()
session.hooks['response'].append(logRoundtrip)
দ্বিতীয়ত, লগিং কনফিগারেশনটি ব্যবহারের জন্য অভিযোজিত করতে হবে logging.handlers.HTTPHandler
(যা ক্রোনোলজার বুঝতে পারে)।
import logging.handlers
chrono = logging.handlers.HTTPHandler(
'localhost:8080', '/api/v1/record', 'POST', credentials=('logger', ''))
handlers = [logging.StreamHandler(), chrono]
logging.basicConfig(level=logging.DEBUG, handlers=handlers)
অবশেষে, ক্রোনোলগার দৌড়ুন run যেমন ডকার ব্যবহার:
docker run --rm -it -p 8080:8080 -v /tmp/db \
-e CHRONOLOGER_STORAGE_DSN=sqlite:////tmp/db/chrono.sqlite \
-e CHRONOLOGER_SECRET=example \
-e CHRONOLOGER_ROLES="basic-reader query-reader writer" \
saaj/chronologer \
python -m chronologer -e production serve -u www-data -g www-data -m
এবং অনুরোধগুলি আবার চালনা করুন:
session.get('https://httpbin.org/user-agent')
session.get('https://httpbin.org/status/200')
স্ট্রিম হ্যান্ডলার উত্পাদন করবে:
DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1): httpbin.org:443
DEBUG:urllib3.connectionpool:https://httpbin.org:443 "GET /user-agent HTTP/1.1" 200 45
DEBUG:httplogger:HTTP roundtrip
DEBUG:urllib3.connectionpool:https://httpbin.org:443 "GET /status/200 HTTP/1.1" 200 0
DEBUG:httplogger:HTTP roundtrip
এখন আপনি যদি http: // লোকালহোস্ট: 8080 / (বেসিক লেখকের পপআপের জন্য ব্যবহারকারীর নাম এবং খালি পাসওয়ার্ডের জন্য "লগার" ব্যবহার করেন) এবং "ওপেন" বোতামটি ক্লিক করেন, আপনার কিছু দেখতে হবে: