|
7 | 7 | import os |
8 | 8 | import sys |
9 | 9 | import time |
| 10 | +from logging import getLogger |
10 | 11 | from typing import TYPE_CHECKING, Any, Dict, Iterable, List, Optional |
11 | 12 |
|
12 | 13 | import requests |
|
26 | 27 | if TYPE_CHECKING: |
27 | 28 | from linodecli.cli import CLI |
28 | 29 |
|
| 30 | +logger = getLogger(__name__) |
| 31 | + |
29 | 32 |
|
30 | 33 | def get_all_pages( |
31 | 34 | ctx: "CLI", operation: OpenAPIOperation, args: List[str] |
@@ -103,13 +106,18 @@ def do_request( |
103 | 106 |
|
104 | 107 | # Print response debug info is requested |
105 | 108 | if ctx.debug_request: |
106 | | - _print_request_debug_info(method, url, headers, body) |
| 109 | + # Multiline log entries aren't ideal, we should consider |
| 110 | + # using single-line structured logging in the future. |
| 111 | + logger.debug( |
| 112 | + "\n%s", |
| 113 | + "\n".join(_format_request_for_log(method, url, headers, body)), |
| 114 | + ) |
107 | 115 |
|
108 | 116 | result = method(url, headers=headers, data=body, verify=API_CA_PATH) |
109 | 117 |
|
110 | 118 | # Print response debug info is requested |
111 | 119 | if ctx.debug_request: |
112 | | - _print_response_debug_info(result) |
| 120 | + logger.debug("\n%s", "\n".join(_format_response_for_log(result))) |
113 | 121 |
|
114 | 122 | # Retry the request if necessary |
115 | 123 | while _check_retry(result) and not ctx.no_retry and ctx.retry_count < 3: |
@@ -362,48 +370,61 @@ def _build_request_body( |
362 | 370 | return json.dumps(_traverse_request_body(expanded_json)) |
363 | 371 |
|
364 | 372 |
|
365 | | -def _print_request_debug_info( |
366 | | - method: Any, url: str, headers: Dict[str, Any], body: Optional[str] |
367 | | -) -> None: |
| 373 | +def _format_request_for_log( |
| 374 | + method: Any, |
| 375 | + url: str, |
| 376 | + headers: Dict[str, str], |
| 377 | + body: str, |
| 378 | +) -> List[str]: |
368 | 379 | """ |
369 | | - Prints debug info for an HTTP request. |
| 380 | + Builds a debug output for the given request. |
370 | 381 |
|
371 | | - :param method: An object with a `__name__` attribute representing |
372 | | - the HTTP method (e.g., "get", "post"). |
373 | | - :param url: The full request URL. |
374 | | - :param headers: A dictionary of request headers. |
375 | | - :param body: The request body as a string, or None if no body exists. |
| 382 | + :param method: The HTTP method of the request. |
| 383 | + :param url: The URL of the request. |
| 384 | + :param headers: The headers of the request. |
| 385 | + :param body: The body of the request. |
| 386 | +
|
| 387 | + :returns: The lines of the generated debug output. |
376 | 388 | """ |
377 | | - print(f"> {method.__name__.upper()} {url}", file=sys.stderr) |
| 389 | + result = [f"> {method.__name__.upper()} {url}"] |
| 390 | + |
378 | 391 | for k, v in headers.items(): |
379 | 392 | # If this is the Authorization header, sanitize the token |
380 | 393 | if k.lower() == "authorization": |
381 | 394 | v = "Bearer " + "*" * 64 |
382 | | - print(f"> {k}: {v}", file=sys.stderr) |
383 | | - print("> Body:", file=sys.stderr) |
384 | | - print("> ", body or "", file=sys.stderr) |
385 | | - print("> ", file=sys.stderr) |
| 395 | + |
| 396 | + result.append(f"> {k}: {v}") |
| 397 | + |
| 398 | + result.extend(["> Body:", f"> {body or ''}", "> "]) |
| 399 | + |
| 400 | + return result |
386 | 401 |
|
387 | 402 |
|
388 | | -def _print_response_debug_info(response: Any) -> None: |
| 403 | +def _format_response_for_log( |
| 404 | + response: requests.Response, |
| 405 | +): |
389 | 406 | """ |
390 | | - Prints debug info for a response from requests. |
| 407 | + Builds a debug output for the given response. |
391 | 408 |
|
392 | | - :param response: The response object returned by a `requests` call. |
| 409 | + :param response: The HTTP response to format. |
| 410 | +
|
| 411 | + :returns: The lines of the generated debug output. |
393 | 412 | """ |
| 413 | + |
394 | 414 | # these come back as ints, convert to HTTP version |
395 | 415 | http_version = response.raw.version / 10 |
396 | 416 | body = response.content.decode("utf-8", errors="replace") |
397 | 417 |
|
398 | | - print( |
399 | | - f"< HTTP/{http_version:.1f} {response.status_code} {response.reason}", |
400 | | - file=sys.stderr, |
401 | | - ) |
| 418 | + result = [ |
| 419 | + f"< HTTP/{http_version:.1f} {response.status_code} {response.reason}" |
| 420 | + ] |
| 421 | + |
402 | 422 | for k, v in response.headers.items(): |
403 | | - print(f"< {k}: {v}", file=sys.stderr) |
404 | | - print("< Body:", file=sys.stderr) |
405 | | - print("< ", body or "", file=sys.stderr) |
406 | | - print("< ", file=sys.stderr) |
| 423 | + result.append(f"< {k}: {v}") |
| 424 | + |
| 425 | + result.extend(["< Body:", f"< {body or ''}", "< "]) |
| 426 | + |
| 427 | + return result |
407 | 428 |
|
408 | 429 |
|
409 | 430 | def _attempt_warn_old_version(ctx: "CLI", result: Any) -> None: |
|
0 commit comments