-
-
Notifications
You must be signed in to change notification settings - Fork 844
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use standard logging style #2547
Changes from all commits
a21571d
ca1f033
c1a0d44
e0f9056
6411bb5
21b47da
bda2e05
e4db10a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
# Logging | ||
|
||
If you need to inspect the internal behaviour of `httpx`, you can use Python's standard logging to output information about the underlying network behaviour. | ||
|
||
For example, the following configuration... | ||
|
||
```python | ||
import logging | ||
import httpx | ||
|
||
logging.basicConfig( | ||
format="%(levelname)s [%(asctime)s] %(name)s - %(message)s", | ||
datefmt="%Y-%m-%d %H:%M:%S", | ||
level=logging.DEBUG | ||
) | ||
|
||
httpx.get("https://www.example.com") | ||
``` | ||
|
||
Will send debug level output to the console, or wherever `stdout` is directed too... | ||
|
||
``` | ||
DEBUG [2023-03-16 14:36:20] httpx - load_ssl_context verify=True cert=None trust_env=True http2=False | ||
DEBUG [2023-03-16 14:36:20] httpx - load_verify_locations cafile='/Users/tomchristie/GitHub/encode/httpx/venv/lib/python3.10/site-packages/certifi/cacert.pem' | ||
DEBUG [2023-03-16 14:36:20] httpcore - connection.connect_tcp.started host='www.example.com' port=443 local_address=None timeout=5.0 | ||
DEBUG [2023-03-16 14:36:20] httpcore - connection.connect_tcp.complete return_value=<httpcore.backends.sync.SyncStream object at 0x1068fd270> | ||
DEBUG [2023-03-16 14:36:20] httpcore - connection.start_tls.started ssl_context=<ssl.SSLContext object at 0x10689aa40> server_hostname='www.example.com' timeout=5.0 | ||
DEBUG [2023-03-16 14:36:20] httpcore - connection.start_tls.complete return_value=<httpcore.backends.sync.SyncStream object at 0x1068fd240> | ||
DEBUG [2023-03-16 14:36:20] httpcore - http11.send_request_headers.started request=<Request [b'GET']> | ||
DEBUG [2023-03-16 14:36:20] httpcore - http11.send_request_headers.complete | ||
DEBUG [2023-03-16 14:36:20] httpcore - http11.send_request_body.started request=<Request [b'GET']> | ||
DEBUG [2023-03-16 14:36:20] httpcore - http11.send_request_body.complete | ||
DEBUG [2023-03-16 14:36:20] httpcore - http11.receive_response_headers.started request=<Request [b'GET']> | ||
DEBUG [2023-03-16 14:36:21] httpcore - http11.receive_response_headers.complete return_value=(b'HTTP/1.1', 200, b'OK', [(b'Content-Encoding', b'gzip'), (b'Accept-Ranges', b'bytes'), (b'Age', b'507675'), (b'Cache-Control', b'max-age=604800'), (b'Content-Type', b'text/html; charset=UTF-8'), (b'Date', b'Thu, 16 Mar 2023 14:36:21 GMT'), (b'Etag', b'"3147526947+ident"'), (b'Expires', b'Thu, 23 Mar 2023 14:36:21 GMT'), (b'Last-Modified', b'Thu, 17 Oct 2019 07:18:26 GMT'), (b'Server', b'ECS (nyb/1D2E)'), (b'Vary', b'Accept-Encoding'), (b'X-Cache', b'HIT'), (b'Content-Length', b'648')]) | ||
INFO [2023-03-16 14:36:21] httpx - HTTP Request: GET https://www.example.com "HTTP/1.1 200 OK" | ||
DEBUG [2023-03-16 14:36:21] httpcore - http11.receive_response_body.started request=<Request [b'GET']> | ||
DEBUG [2023-03-16 14:36:21] httpcore - http11.receive_response_body.complete | ||
DEBUG [2023-03-16 14:36:21] httpcore - http11.response_closed.started | ||
DEBUG [2023-03-16 14:36:21] httpcore - http11.response_closed.complete | ||
DEBUG [2023-03-16 14:36:21] httpcore - connection.close.started | ||
DEBUG [2023-03-16 14:36:21] httpcore - connection.close.complete | ||
``` | ||
|
||
Logging output includes information from both the high-level `httpx` logger, and the network-level `httpcore` logger, which can be configured seperately. | ||
|
||
For handling more complex logging configurations you might want to use the dictionary configuration style... | ||
|
||
```python | ||
import logging.config | ||
import httpx | ||
|
||
LOGGING_CONFIG = { | ||
"version": 1, | ||
"handlers": { | ||
"default": { | ||
"class": "logging.StreamHandler", | ||
"formatter": "http", | ||
"stream": "ext://sys.stderr" | ||
} | ||
}, | ||
"formatters": { | ||
"http": { | ||
"format": "%(levelname)s [%(asctime)s] %(name)s - %(message)s", | ||
"datefmt": "%Y-%m-%d %H:%M:%S", | ||
} | ||
}, | ||
'loggers': { | ||
'httpx': { | ||
'handlers': ['default'], | ||
'level': 'DEBUG', | ||
}, | ||
'httpcore': { | ||
'handlers': ['default'], | ||
'level': 'DEBUG', | ||
}, | ||
} | ||
} | ||
|
||
logging.config.dictConfig(LOGGING_CONFIG) | ||
httpx.get('https://www.example.com') | ||
``` | ||
|
||
The exact formatting of the debug logging may be subject to change across different versions of `httpx` and `httpcore`. If you need to rely on a particular format it is recommended that you pin installation of these packages to fixed versions. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
import datetime | ||
import enum | ||
import logging | ||
import typing | ||
import warnings | ||
from contextlib import asynccontextmanager, contextmanager | ||
|
@@ -50,7 +51,6 @@ | |
Timer, | ||
URLPattern, | ||
get_environment_proxies, | ||
get_logger, | ||
is_https_redirect, | ||
same_origin, | ||
) | ||
|
@@ -84,7 +84,7 @@ class UseClientDefault: | |
USE_CLIENT_DEFAULT = UseClientDefault() | ||
|
||
|
||
logger = get_logger(__name__) | ||
logger = logging.getLogger("httpx") | ||
|
||
USER_AGENT = f"python-httpx/{__version__}" | ||
ACCEPT_ENCODING = ", ".join( | ||
|
@@ -1010,10 +1010,13 @@ def _send_single_request(self, request: Request) -> Response: | |
self.cookies.extract_cookies(response) | ||
response.default_encoding = self._default_encoding | ||
|
||
status = f"{response.status_code} {response.reason_phrase}" | ||
response_line = f"{response.http_version} {status}" | ||
logger.debug( | ||
'HTTP Request: %s %s "%s"', request.method, request.url, response_line | ||
logger.info( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Based on the other python packages, I don't recall any other python client having an INFO log message level. 🤔 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i.e. can't it be debug as well? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It could yes, though it's less useful to have logging if everything is at the same level. (Similar: gunicorn, uvicorn using INFO for requests, and DEBUG for other stuffs) |
||
'HTTP Request: %s %s "%s %d %s"', | ||
request.method, | ||
request.url, | ||
response.http_version, | ||
response.status_code, | ||
response.reason_phrase, | ||
) | ||
|
||
return response | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that this
TRACE
documentation was already incorrect at this point since we losthttpcore
logging for a while.