mirror of
https://git.datalinker.icu/comfyanonymous/ComfyUI
synced 2026-09-04 20:37:11 +08:00
add logging to /temp
This commit is contained in:
parent
4cfedbc6c7
commit
ffc6b610b6
@ -101,9 +101,11 @@ import json
|
|||||||
import requests
|
import requests
|
||||||
from urllib.parse import urljoin, urlparse
|
from urllib.parse import urljoin, urlparse
|
||||||
from pydantic import BaseModel, Field
|
from pydantic import BaseModel, Field
|
||||||
|
import uuid # For generating unique operation IDs
|
||||||
|
|
||||||
from comfy.cli_args import args
|
from comfy.cli_args import args
|
||||||
from comfy import utils
|
from comfy import utils
|
||||||
|
from . import request_logger
|
||||||
|
|
||||||
T = TypeVar("T", bound=BaseModel)
|
T = TypeVar("T", bound=BaseModel)
|
||||||
R = TypeVar("R", bound=BaseModel)
|
R = TypeVar("R", bound=BaseModel)
|
||||||
@ -184,6 +186,10 @@ class ApiClient:
|
|||||||
# 500, 502, 503, 504 (Server Errors)
|
# 500, 502, 503, 504 (Server Errors)
|
||||||
self.retry_status_codes = retry_status_codes or (408, 429, 500, 502, 503, 504)
|
self.retry_status_codes = retry_status_codes or (408, 429, 500, 502, 503, 504)
|
||||||
|
|
||||||
|
def _generate_operation_id(self, path: str) -> str:
|
||||||
|
"""Generates a unique operation ID for logging."""
|
||||||
|
return f"{path.strip('/').replace('/', '_')}_{uuid.uuid4().hex[:8]}"
|
||||||
|
|
||||||
def _create_json_payload_args(
|
def _create_json_payload_args(
|
||||||
self,
|
self,
|
||||||
data: Optional[Dict[str, Any]] = None,
|
data: Optional[Dict[str, Any]] = None,
|
||||||
@ -345,6 +351,16 @@ class ApiClient:
|
|||||||
else:
|
else:
|
||||||
payload_args = self._create_json_payload_args(data, request_headers)
|
payload_args = self._create_json_payload_args(data, request_headers)
|
||||||
|
|
||||||
|
operation_id = self._generate_operation_id(path)
|
||||||
|
request_logger.log_request_response(
|
||||||
|
operation_id=operation_id,
|
||||||
|
request_method=method,
|
||||||
|
request_url=url,
|
||||||
|
request_headers=request_headers,
|
||||||
|
request_params=params,
|
||||||
|
request_data=data if content_type == "application/json" else "[form-data or other]"
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
response = requests.request(
|
response = requests.request(
|
||||||
method=method,
|
method=method,
|
||||||
@ -383,7 +399,31 @@ class ApiClient:
|
|||||||
# Raise exception for error status codes
|
# Raise exception for error status codes
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
|
|
||||||
|
# Log successful response
|
||||||
|
response_content_to_log = response.content
|
||||||
|
try:
|
||||||
|
# Attempt to parse JSON for prettier logging, fallback to raw content
|
||||||
|
response_content_to_log = response.json()
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
pass # Keep as bytes/str if not JSON
|
||||||
|
|
||||||
|
request_logger.log_request_response(
|
||||||
|
operation_id=operation_id,
|
||||||
|
request_method=method, # Pass request details again for context in log
|
||||||
|
request_url=url,
|
||||||
|
response_status_code=response.status_code,
|
||||||
|
response_headers=dict(response.headers),
|
||||||
|
response_content=response_content_to_log
|
||||||
|
)
|
||||||
|
|
||||||
except requests.ConnectionError as e:
|
except requests.ConnectionError as e:
|
||||||
|
error_message = f"ConnectionError: {str(e)}"
|
||||||
|
request_logger.log_request_response(
|
||||||
|
operation_id=operation_id,
|
||||||
|
request_method=method,
|
||||||
|
request_url=url,
|
||||||
|
error_message=error_message
|
||||||
|
)
|
||||||
# Only perform connectivity check if we've exhausted all retries
|
# Only perform connectivity check if we've exhausted all retries
|
||||||
if retry_count >= self.max_retries:
|
if retry_count >= self.max_retries:
|
||||||
# Check connectivity to determine if it's a local or API issue
|
# Check connectivity to determine if it's a local or API issue
|
||||||
@ -422,12 +462,24 @@ class ApiClient:
|
|||||||
|
|
||||||
# If we've exhausted retries and didn't identify the specific issue,
|
# If we've exhausted retries and didn't identify the specific issue,
|
||||||
# raise a generic exception
|
# raise a generic exception
|
||||||
raise Exception(
|
final_error_message = (
|
||||||
f"Unable to connect to the API server after {self.max_retries} attempts. "
|
f"Unable to connect to the API server after {self.max_retries} attempts. "
|
||||||
f"Please check your internet connection or try again later."
|
f"Please check your internet connection or try again later."
|
||||||
) from e
|
)
|
||||||
|
request_logger.log_request_response( # Log final failure
|
||||||
|
operation_id=operation_id,
|
||||||
|
request_method=method, request_url=url,
|
||||||
|
error_message=final_error_message
|
||||||
|
)
|
||||||
|
raise Exception(final_error_message) from e
|
||||||
|
|
||||||
except requests.Timeout as e:
|
except requests.Timeout as e:
|
||||||
|
error_message = f"Timeout: {str(e)}"
|
||||||
|
request_logger.log_request_response(
|
||||||
|
operation_id=operation_id,
|
||||||
|
request_method=method, request_url=url,
|
||||||
|
error_message=error_message
|
||||||
|
)
|
||||||
# Retry timeouts if we haven't exhausted retries
|
# Retry timeouts if we haven't exhausted retries
|
||||||
if retry_count < self.max_retries:
|
if retry_count < self.max_retries:
|
||||||
delay = self.retry_delay * (self.retry_backoff_factor ** retry_count)
|
delay = self.retry_delay * (self.retry_backoff_factor ** retry_count)
|
||||||
@ -447,34 +499,64 @@ class ApiClient:
|
|||||||
multipart_parser=multipart_parser,
|
multipart_parser=multipart_parser,
|
||||||
retry_count=retry_count + 1,
|
retry_count=retry_count + 1,
|
||||||
)
|
)
|
||||||
|
final_error_message = (
|
||||||
raise Exception(
|
|
||||||
f"Request timed out after {self.timeout} seconds and {self.max_retries} retry attempts. "
|
f"Request timed out after {self.timeout} seconds and {self.max_retries} retry attempts. "
|
||||||
f"The server might be experiencing high load or the operation is taking longer than expected."
|
f"The server might be experiencing high load or the operation is taking longer than expected."
|
||||||
) from e
|
)
|
||||||
|
request_logger.log_request_response( # Log final failure
|
||||||
|
operation_id=operation_id,
|
||||||
|
request_method=method, request_url=url,
|
||||||
|
error_message=final_error_message
|
||||||
|
)
|
||||||
|
raise Exception(final_error_message) from e
|
||||||
|
|
||||||
except requests.HTTPError as e:
|
except requests.HTTPError as e:
|
||||||
status_code = e.response.status_code if hasattr(e, "response") else None
|
status_code = e.response.status_code if hasattr(e, "response") else None
|
||||||
error_message = f"HTTP Error: {str(e)}"
|
original_error_message = f"HTTP Error: {str(e)}"
|
||||||
|
error_content_for_log = None
|
||||||
# Try to extract detailed error message from JSON response
|
if hasattr(e, "response") and e.response is not None:
|
||||||
|
error_content_for_log = e.response.content
|
||||||
try:
|
try:
|
||||||
if hasattr(e, "response") and e.response.content:
|
error_content_for_log = e.response.json()
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# Try to extract detailed error message from JSON response for user display
|
||||||
|
# but log the full error content.
|
||||||
|
user_display_error_message = original_error_message
|
||||||
|
|
||||||
|
try:
|
||||||
|
if hasattr(e, "response") and e.response is not None and e.response.content:
|
||||||
error_json = e.response.json()
|
error_json = e.response.json()
|
||||||
if "error" in error_json and "message" in error_json["error"]:
|
if "error" in error_json and "message" in error_json["error"]:
|
||||||
error_message = f"API Error: {error_json['error']['message']}"
|
user_display_error_message = f"API Error: {error_json['error']['message']}"
|
||||||
if "type" in error_json["error"]:
|
if "type" in error_json["error"]:
|
||||||
error_message += f" (Type: {error_json['error']['type']})"
|
user_display_error_message += f" (Type: {error_json['error']['type']})"
|
||||||
|
elif isinstance(error_json, dict): # Handle cases where error is just a JSON dict
|
||||||
|
user_display_error_message = f"API Error: {json.dumps(error_json)}"
|
||||||
|
else: # Non-dict JSON error
|
||||||
|
user_display_error_message = f"API Error: {str(error_json)}"
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
# If not JSON, use the raw content if it's not too long, or a summary
|
||||||
|
if hasattr(e, "response") and e.response is not None and e.response.content:
|
||||||
|
raw_content = e.response.content.decode(errors='ignore')
|
||||||
|
if len(raw_content) < 200: # Arbitrary limit for display
|
||||||
|
user_display_error_message = f"API Error (raw): {raw_content}"
|
||||||
else:
|
else:
|
||||||
error_message = f"API Error: {error_json}"
|
user_display_error_message = f"API Error (raw, status {status_code})"
|
||||||
except Exception as json_error:
|
|
||||||
# If we can't parse the JSON, fall back to the original error message
|
request_logger.log_request_response(
|
||||||
logging.debug(
|
operation_id=operation_id,
|
||||||
f"[DEBUG] Failed to parse error response: {str(json_error)}"
|
request_method=method, request_url=url,
|
||||||
|
response_status_code=status_code,
|
||||||
|
response_headers=dict(e.response.headers) if hasattr(e, "response") and e.response is not None else None,
|
||||||
|
response_content=error_content_for_log,
|
||||||
|
error_message=original_error_message # Log the original exception string as error
|
||||||
)
|
)
|
||||||
|
|
||||||
logging.debug(f"[DEBUG] API Error: {error_message} (Status: {status_code})")
|
logging.debug(f"[DEBUG] API Error: {user_display_error_message} (Status: {status_code})")
|
||||||
if hasattr(e, "response") and e.response.content:
|
if hasattr(e, "response") and e.response is not None and e.response.content:
|
||||||
logging.debug(f"[DEBUG] Response content: {e.response.content}")
|
logging.debug(f"[DEBUG] Response content: {e.response.content}")
|
||||||
|
|
||||||
# Retry if the status code is in our retry list and we haven't exhausted retries
|
# Retry if the status code is in our retry list and we haven't exhausted retries
|
||||||
@ -499,17 +581,18 @@ class ApiClient:
|
|||||||
retry_count=retry_count + 1,
|
retry_count=retry_count + 1,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Specific error messages for common status codes
|
# Specific error messages for common status codes for user display
|
||||||
if status_code == 401:
|
if status_code == 401:
|
||||||
error_message = "Unauthorized: Please login first to use this node."
|
user_display_error_message = "Unauthorized: Please login first to use this node."
|
||||||
elif status_code == 402:
|
elif status_code == 402:
|
||||||
error_message = "Payment Required: Please add credits to your account to use this node."
|
user_display_error_message = "Payment Required: Please add credits to your account to use this node."
|
||||||
elif status_code == 409:
|
elif status_code == 409:
|
||||||
error_message = "There is a problem with your account. Please contact support@comfy.org."
|
user_display_error_message = "There is a problem with your account. Please contact support@comfy.org."
|
||||||
elif status_code == 429:
|
elif status_code == 429:
|
||||||
error_message = "Rate Limit Exceeded: Please try again later."
|
user_display_error_message = "Rate Limit Exceeded: Please try again later."
|
||||||
|
# else, user_display_error_message remains as parsed from response or original HTTPError string
|
||||||
|
|
||||||
raise Exception(error_message)
|
raise Exception(user_display_error_message) # Raise with the user-friendly message
|
||||||
|
|
||||||
# Parse and return JSON response
|
# Parse and return JSON response
|
||||||
if response.content:
|
if response.content:
|
||||||
@ -557,46 +640,96 @@ class ApiClient:
|
|||||||
|
|
||||||
# Try the upload with retries
|
# Try the upload with retries
|
||||||
last_exception = None
|
last_exception = None
|
||||||
for retry in range(max_retries + 1):
|
operation_id = f"upload_{upload_url.split('/')[-1]}_{uuid.uuid4().hex[:8]}" # Simplified ID for uploads
|
||||||
|
|
||||||
|
# Log initial attempt (without full file data for brevity)
|
||||||
|
request_logger.log_request_response(
|
||||||
|
operation_id=operation_id,
|
||||||
|
request_method="PUT",
|
||||||
|
request_url=upload_url,
|
||||||
|
request_headers=headers,
|
||||||
|
request_data=f"[File data of type {content_type or 'unknown'}, size {len(data)} bytes]"
|
||||||
|
)
|
||||||
|
|
||||||
|
for retry_attempt in range(max_retries + 1):
|
||||||
try:
|
try:
|
||||||
response = requests.put(upload_url, data=data, headers=headers)
|
response = requests.put(upload_url, data=data, headers=headers)
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
|
request_logger.log_request_response(
|
||||||
|
operation_id=operation_id,
|
||||||
|
request_method="PUT", request_url=upload_url, # For context
|
||||||
|
response_status_code=response.status_code,
|
||||||
|
response_headers=dict(response.headers),
|
||||||
|
response_content="File uploaded successfully." # Or response.text if available
|
||||||
|
)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
except (requests.ConnectionError, requests.Timeout, requests.HTTPError) as e:
|
except (requests.ConnectionError, requests.Timeout, requests.HTTPError) as e:
|
||||||
last_exception = e
|
last_exception = e
|
||||||
if retry < max_retries:
|
error_message_for_log = f"{type(e).__name__}: {str(e)}"
|
||||||
delay = retry_delay * (retry_backoff_factor ** retry)
|
response_content_for_log = None
|
||||||
|
status_code_for_log = None
|
||||||
|
headers_for_log = None
|
||||||
|
|
||||||
|
if hasattr(e, 'response') and e.response is not None:
|
||||||
|
status_code_for_log = e.response.status_code
|
||||||
|
headers_for_log = dict(e.response.headers)
|
||||||
|
try:
|
||||||
|
response_content_for_log = e.response.json()
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
response_content_for_log = e.response.content
|
||||||
|
|
||||||
|
|
||||||
|
request_logger.log_request_response(
|
||||||
|
operation_id=operation_id,
|
||||||
|
request_method="PUT", request_url=upload_url,
|
||||||
|
response_status_code=status_code_for_log,
|
||||||
|
response_headers=headers_for_log,
|
||||||
|
response_content=response_content_for_log,
|
||||||
|
error_message=error_message_for_log
|
||||||
|
)
|
||||||
|
|
||||||
|
if retry_attempt < max_retries:
|
||||||
|
delay = retry_delay * (retry_backoff_factor ** retry_attempt)
|
||||||
logging.warning(
|
logging.warning(
|
||||||
f"File upload failed: {str(e)}. "
|
f"File upload failed: {str(e)}. "
|
||||||
f"Retrying in {delay:.2f}s ({retry + 1}/{max_retries})"
|
f"Retrying in {delay:.2f}s ({retry_attempt + 1}/{max_retries})"
|
||||||
)
|
)
|
||||||
time.sleep(delay)
|
time.sleep(delay)
|
||||||
else:
|
else:
|
||||||
break
|
break # Max retries reached
|
||||||
|
|
||||||
# If we've exhausted all retries, check if it's a network issue
|
# If we've exhausted all retries, determine the final error type and raise
|
||||||
|
final_error_message = f"Failed to upload file after {max_retries + 1} attempts. Error: {str(last_exception)}"
|
||||||
try:
|
try:
|
||||||
# Try to determine if it's a local network issue
|
# Check basic internet connectivity
|
||||||
check_response = requests.get("https://www.google.com", timeout=5.0)
|
check_response = requests.get("https://www.google.com", timeout=5.0, verify=True) # Assuming verify=True is desired
|
||||||
if check_response.status_code < 500:
|
if check_response.status_code >= 500: # Google itself has an issue (rare)
|
||||||
# Internet works but upload failed, likely a server or URL issue
|
final_error_message = (f"Failed to upload file. Internet connectivity check to Google failed "
|
||||||
raise Exception(
|
f"(status {check_response.status_code}). Original error: {str(last_exception)}")
|
||||||
f"Failed to upload file after {max_retries} attempts. "
|
# Not raising LocalNetworkError here as Google itself might be down.
|
||||||
f"The upload service may be experiencing issues. Error: {str(last_exception)}"
|
# If Google is reachable, the issue is likely with the upload server or a more specific local problem
|
||||||
) from last_exception
|
# not caught by a simple Google ping (e.g., DNS for the specific upload URL, firewall).
|
||||||
else:
|
# The original last_exception is probably most relevant.
|
||||||
# Even Google check failed, likely a local network issue
|
|
||||||
raise LocalNetworkError(
|
except (requests.RequestException, socket.error) as conn_check_exc:
|
||||||
f"Failed to upload file due to network connectivity issues. "
|
# Could not reach Google, likely a local network issue
|
||||||
f"Please check your internet connection and try again."
|
final_error_message = (f"Failed to upload file due to network connectivity issues "
|
||||||
) from last_exception
|
f"(cannot reach Google: {str(conn_check_exc)}). "
|
||||||
except (requests.RequestException, socket.error):
|
f"Original upload error: {str(last_exception)}")
|
||||||
# Could not reach Google, definitely a local network issue
|
request_logger.log_request_response( # Log final failure reason
|
||||||
raise LocalNetworkError(
|
operation_id=operation_id,
|
||||||
f"Failed to upload file due to network connectivity issues. "
|
request_method="PUT", request_url=upload_url,
|
||||||
f"Please check your internet connection and try again."
|
error_message=final_error_message
|
||||||
) from last_exception
|
)
|
||||||
|
raise LocalNetworkError(final_error_message) from last_exception
|
||||||
|
|
||||||
|
request_logger.log_request_response( # Log final failure reason if not LocalNetworkError
|
||||||
|
operation_id=operation_id,
|
||||||
|
request_method="PUT", request_url=upload_url,
|
||||||
|
error_message=final_error_message
|
||||||
|
)
|
||||||
|
raise Exception(final_error_message) from last_exception
|
||||||
|
|
||||||
|
|
||||||
class ApiEndpoint(Generic[T, R]):
|
class ApiEndpoint(Generic[T, R]):
|
||||||
|
|||||||
126
comfy_api_nodes/apis/request_logger.py
Normal file
126
comfy_api_nodes/apis/request_logger.py
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
import os
|
||||||
|
import datetime
|
||||||
|
import json
|
||||||
|
import logging
|
||||||
|
import folder_paths
|
||||||
|
|
||||||
|
# Get the logger instance
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
def get_log_directory():
|
||||||
|
"""
|
||||||
|
Ensures the API log directory exists within ComfyUI's temp directory
|
||||||
|
and returns its path.
|
||||||
|
"""
|
||||||
|
base_temp_dir = folder_paths.get_temp_directory()
|
||||||
|
log_dir = os.path.join(base_temp_dir, "api_logs")
|
||||||
|
try:
|
||||||
|
os.makedirs(log_dir, exist_ok=True)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error creating API log directory {log_dir}: {e}")
|
||||||
|
# Fallback to base temp directory if sub-directory creation fails
|
||||||
|
return base_temp_dir
|
||||||
|
return log_dir
|
||||||
|
|
||||||
|
def _format_data_for_logging(data):
|
||||||
|
"""Helper to format data (dict, str, bytes) for logging."""
|
||||||
|
if isinstance(data, bytes):
|
||||||
|
try:
|
||||||
|
return data.decode('utf-8') # Try to decode as text
|
||||||
|
except UnicodeDecodeError:
|
||||||
|
return f"[Binary data of length {len(data)} bytes]"
|
||||||
|
elif isinstance(data, (dict, list)):
|
||||||
|
try:
|
||||||
|
return json.dumps(data, indent=2, ensure_ascii=False)
|
||||||
|
except TypeError:
|
||||||
|
return str(data) # Fallback for non-serializable objects
|
||||||
|
return str(data)
|
||||||
|
|
||||||
|
def log_request_response(
|
||||||
|
operation_id: str,
|
||||||
|
request_method: str,
|
||||||
|
request_url: str,
|
||||||
|
request_headers: dict | None = None,
|
||||||
|
request_params: dict | None = None,
|
||||||
|
request_data: any = None,
|
||||||
|
response_status_code: int | None = None,
|
||||||
|
response_headers: dict | None = None,
|
||||||
|
response_content: any = None,
|
||||||
|
error_message: str | None = None
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Logs API request and response details to a file in the temp/api_logs directory.
|
||||||
|
"""
|
||||||
|
log_dir = get_log_directory()
|
||||||
|
timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S_%f")
|
||||||
|
filename = f"{timestamp}_{operation_id.replace('/', '_').replace(':', '_')}.log"
|
||||||
|
filepath = os.path.join(log_dir, filename)
|
||||||
|
|
||||||
|
log_content = []
|
||||||
|
|
||||||
|
log_content.append(f"Timestamp: {datetime.datetime.now().isoformat()}")
|
||||||
|
log_content.append(f"Operation ID: {operation_id}")
|
||||||
|
log_content.append("-" * 30 + " REQUEST " + "-" * 30)
|
||||||
|
log_content.append(f"Method: {request_method}")
|
||||||
|
log_content.append(f"URL: {request_url}")
|
||||||
|
if request_headers:
|
||||||
|
log_content.append(f"Headers:\n{_format_data_for_logging(request_headers)}")
|
||||||
|
if request_params:
|
||||||
|
log_content.append(f"Params:\n{_format_data_for_logging(request_params)}")
|
||||||
|
if request_data:
|
||||||
|
log_content.append(f"Data/Body:\n{_format_data_for_logging(request_data)}")
|
||||||
|
|
||||||
|
log_content.append("\n" + "-" * 30 + " RESPONSE " + "-" * 30)
|
||||||
|
if response_status_code is not None:
|
||||||
|
log_content.append(f"Status Code: {response_status_code}")
|
||||||
|
if response_headers:
|
||||||
|
log_content.append(f"Headers:\n{_format_data_for_logging(response_headers)}")
|
||||||
|
if response_content:
|
||||||
|
log_content.append(f"Content:\n{_format_data_for_logging(response_content)}")
|
||||||
|
if error_message:
|
||||||
|
log_content.append(f"Error:\n{error_message}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(filepath, "w", encoding="utf-8") as f:
|
||||||
|
f.write("\n".join(log_content))
|
||||||
|
logger.debug(f"API log saved to: {filepath}")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error writing API log to {filepath}: {e}")
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
# Example usage (for testing the logger directly)
|
||||||
|
logger.setLevel(logging.DEBUG)
|
||||||
|
# Mock folder_paths for direct execution if not running within ComfyUI full context
|
||||||
|
if not hasattr(folder_paths, 'get_temp_directory'):
|
||||||
|
class MockFolderPaths:
|
||||||
|
def get_temp_directory(self):
|
||||||
|
# Create a local temp dir for testing if needed
|
||||||
|
p = os.path.join(os.path.dirname(__file__), 'temp_test_logs')
|
||||||
|
os.makedirs(p, exist_ok=True)
|
||||||
|
return p
|
||||||
|
folder_paths = MockFolderPaths()
|
||||||
|
|
||||||
|
log_request_response(
|
||||||
|
operation_id="test_operation_get",
|
||||||
|
request_method="GET",
|
||||||
|
request_url="https://api.example.com/test",
|
||||||
|
request_headers={"Authorization": "Bearer testtoken"},
|
||||||
|
request_params={"param1": "value1"},
|
||||||
|
response_status_code=200,
|
||||||
|
response_content={"message": "Success!"}
|
||||||
|
)
|
||||||
|
log_request_response(
|
||||||
|
operation_id="test_operation_post_error",
|
||||||
|
request_method="POST",
|
||||||
|
request_url="https://api.example.com/submit",
|
||||||
|
request_data={"key": "value", "nested": {"num": 123}},
|
||||||
|
error_message="Connection timed out"
|
||||||
|
)
|
||||||
|
log_request_response(
|
||||||
|
operation_id="test_binary_response",
|
||||||
|
request_method="GET",
|
||||||
|
request_url="https://api.example.com/image.png",
|
||||||
|
response_status_code=200,
|
||||||
|
response_content=b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR...' # Sample binary data
|
||||||
|
)
|
||||||
|
print(f"Test logs should be in: {get_log_directory()}")
|
||||||
Loading…
x
Reference in New Issue
Block a user