Skip to content

Commit

Permalink
feat: add debug logging
Browse files Browse the repository at this point in the history
  • Loading branch information
pnwpedro committed Oct 10, 2024
1 parent a3ca86d commit 08ff03b
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 7 deletions.
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,23 @@ options = ChangeFeedOptions(
client.change_feed(fql('Product.all().toStream()'), options)
```

## Logging

Debug logging is handled by the standard logging package in under the `fauna` namespace. We will log the request with body, excluding the Authorization header, as well as the full response.

In your application, you can enable debug logging with the following. Given this is a standard convention in Python, you may want more fine-grained control over which libraries log. See Python's how-to at https://docs.python.org/3/howto/logging.html.
```python
import logging
from fauna.client import Client
from fauna import fql

logging.basicConfig(
level=logging.DEBUG
)
c = Client()
c.query(fql("42"))
```

## Setup

```bash
Expand Down
5 changes: 4 additions & 1 deletion fauna/client/client.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import logging
from dataclasses import dataclass
from datetime import timedelta
from typing import Any, Dict, Iterator, Mapping, Optional, Union, List
Expand All @@ -14,6 +15,8 @@
from fauna.query import Query, Page, fql
from fauna.query.models import StreamToken

logger = logging.getLogger("fauna")

DefaultHttpConnectTimeout = timedelta(seconds=5)
DefaultHttpReadTimeout: Optional[timedelta] = None
DefaultHttpWriteTimeout = timedelta(seconds=5)
Expand Down Expand Up @@ -217,7 +220,7 @@ def __init__(
max_keepalive_connections=DefaultMaxIdleConnections,
keepalive_expiry=idle_timeout_s,
),
))
), logger)
fauna.global_http_client = c

self._session = fauna.global_http_client
Expand Down
52 changes: 46 additions & 6 deletions fauna/http/httpx_client.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import json
import logging
from contextlib import contextmanager
from json import JSONDecodeError
from typing import Mapping, Any, Optional, Iterator
Expand Down Expand Up @@ -50,9 +51,10 @@ def close(self) -> None:

class HTTPXClient(HTTPClient):

def __init__(self, client: httpx.Client):
def __init__(self, client: httpx.Client, logger: logging.Logger):
super(HTTPXClient, self).__init__()
self._c = client
self._logger = logger

def request(
self,
Expand All @@ -69,14 +71,29 @@ def request(
json=data,
headers=headers,
)

if self._logger.isEnabledFor(logging.DEBUG):
headers_to_log = request.headers.copy()
headers_to_log.pop("Authorization")
self._logger.debug(
f"query.request method={request.method} url={request.url} headers={headers_to_log} data={data}"
)

except httpx.InvalidURL as e:
raise ClientError("Invalid URL Format") from e

try:
return HTTPXResponse(self._c.send(
response = self._c.send(
request,
stream=False,
))
)

if self._logger.isEnabledFor(logging.DEBUG):
self._logger.debug(
f"query.response status_code={response.status_code} headers={response.headers} data={response.text}"
)

return HTTPXResponse(response)
except (httpx.HTTPError, httpx.InvalidURL) as e:
raise NetworkError("Exception re-raised from HTTP request") from e

Expand All @@ -87,14 +104,37 @@ def stream(
headers: Mapping[str, str],
data: Mapping[str, Any],
) -> Iterator[Any]:
with self._c.stream(
"POST", url=url, headers=headers, json=data) as response:
request = self._c.build_request(
method="POST",
url=url,
headers=headers,
json=data,
)

if self._logger.isEnabledFor(logging.DEBUG):
headers_to_log = request.headers.copy()
headers_to_log.pop("Authorization")
self._logger.debug(
f"stream.request method={request.method} url={request.url} headers={headers_to_log} data={data}"
)

response = self._c.send(
request=request,
stream=True,
)

try:
yield self._transform(response)
finally:
response.close()

def _transform(self, response):
try:
for line in response.iter_lines():
yield json.loads(line)
loaded = json.loads(line)
if self._logger.isEnabledFor(logging.DEBUG):
self._logger.debug(f"stream.data data={loaded}")
yield loaded
except httpx.ReadTimeout as e:
raise NetworkError("Stream timeout") from e
except (httpx.HTTPError, httpx.InvalidURL) as e:
Expand Down

0 comments on commit 08ff03b

Please sign in to comment.