Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 20 additions & 2 deletions src/Client/QuantCloudClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -232,17 +232,27 @@ public function post(string $path, array $data, array $request_options = []): ar
catch (GuzzleException $e) {
$status = NULL;
$reason = NULL;
$body = '';
if ($e instanceof RequestException && $e->getResponse()) {
$status = $e->getResponse()->getStatusCode();
$reason = $e->getResponse()->getReasonPhrase();
$body = (string) $e->getResponse()->getBody();
}
// Government deployments may have PROTECTED data in prompts that flow
// back through upstream error responses. Only log the body when the
// operator has opted in via advanced.enable_logging; otherwise emit a
// hint pointing them at the flag.
$log_body = $config->get('advanced.enable_logging')
? mb_substr($body, 0, 500)
: '<redacted; enable advanced.enable_logging to capture>';
$this->logger->error(
'Quant Dashboard AI request failed for @path after @timeout seconds (status: @status @reason)',
'Quant Dashboard AI request failed for @path after @timeout seconds (status: @status @reason). Response: @body',
[
'@path' => $path,
'@timeout' => $timeout,
'@status' => $status ?? 'n/a',
'@reason' => $reason ?? 'transport error',
'@body' => $log_body,
]
);
throw new \RuntimeException('AI API request failed (status: ' . ($status ?? 'n/a') . ')', 0, $e);
Expand Down Expand Up @@ -411,13 +421,21 @@ public function get(string $path, array $query_params = []): array {
catch (GuzzleException $e) {
$status = NULL;
$reason = NULL;
$body = '';
if ($e instanceof RequestException && $e->getResponse()) {
$status = $e->getResponse()->getStatusCode();
$reason = $e->getResponse()->getReasonPhrase();
$body = (string) $e->getResponse()->getBody();
}
$this->logger->error('Quant Dashboard AI request failed (status: @status @reason)', [
// Government deployments may have PROTECTED data echoed in upstream
// error responses; gate the body behind advanced.enable_logging.
$log_body = $config->get('advanced.enable_logging')
? mb_substr($body, 0, 500)
: '<redacted; enable advanced.enable_logging to capture>';
$this->logger->error('Quant Dashboard AI request failed (status: @status @reason). Response: @body', [
'@status' => $status ?? 'n/a',
'@reason' => $reason ?? 'transport error',
'@body' => $log_body,
]);
throw new \RuntimeException('AI API request failed (status: ' . ($status ?? 'n/a') . ')', 0, $e);
}
Expand Down
30 changes: 27 additions & 3 deletions src/Client/QuantCloudStreamingClient.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

declare(strict_types=1);

namespace Drupal\ai_provider_quant_cloud\Client;

use Psr\Http\Message\StreamInterface;
Expand All @@ -14,7 +16,7 @@ class QuantCloudStreamingClient extends QuantCloudClient {
/**
* Maximum malformed SSE frames to log per streaming request.
*/
protected const MAX_SSE_DECODE_WARNINGS = 3;
public const MAX_SSE_DECODE_WARNINGS = 3;

/**
* Chat with streaming response (SSE) - returns raw stream.
Expand Down Expand Up @@ -82,8 +84,19 @@ public function chatStreamRaw(array $messages, string $model_id, array $options

}
catch (\Exception $e) {
$this->logger->error('Streaming request failed: @message', [
$body = '';
if ($e instanceof \GuzzleHttp\Exception\RequestException && $e->getResponse()) {
$body = (string) $e->getResponse()->getBody();
}
// Government deployments may have PROTECTED data in prompts that flow
// back through upstream error bodies; only log the body when the
// operator has opted in via advanced.enable_logging.
$log_body = $config->get('advanced.enable_logging')
? mb_substr($body, 0, 500)
: '<redacted; enable advanced.enable_logging to capture>';
$this->logger->error('Streaming request failed: @message body=@body', [
'@message' => $e->getMessage(),
'@body' => $log_body,
]);
throw new \RuntimeException('Streaming failed: ' . $e->getMessage(), 0, $e);
}
Expand Down Expand Up @@ -201,8 +214,19 @@ public function chatStream(array $messages, string $model_id, callable $callback

}
catch (\Exception $e) {
$this->logger->error('Streaming request failed: @message', [
$body = '';
if ($e instanceof \GuzzleHttp\Exception\RequestException && $e->getResponse()) {
$body = (string) $e->getResponse()->getBody();
}
// Government deployments may have PROTECTED data in prompts that flow
// back through upstream error bodies; only log the body when the
// operator has opted in via advanced.enable_logging.
$log_body = $config->get('advanced.enable_logging')
? mb_substr($body, 0, 500)
: '<redacted; enable advanced.enable_logging to capture>';
$this->logger->error('Streaming request failed: @message body=@body', [
'@message' => $e->getMessage(),
'@body' => $log_body,
]);
throw new \RuntimeException('Streaming failed: ' . $e->getMessage(), 0, $e);
}
Expand Down
Loading