From 5e0d57cce02c9754ea00bce6d014993761ce266d Mon Sep 17 00:00:00 2001 From: Adam James Date: Thu, 1 Feb 2024 11:57:12 +0000 Subject: [PATCH] Add Graphite Web HTTP request timeout option If the Graphite Web server is unreachable, all requests for frontend pages containing graphs hang until the backend HTTP request times out, resulting in a very poor UX. The Guzzle documentation states that the default behaviour is to wait indefinitely, however in our testing the cURL handler has an internal default of 30 seconds: https://docs.guzzlephp.org/en/stable/request-options.html#timeout This commit makes the HTTP request timeout configurable and sets a reasonable default of 10 seconds. --- application/forms/Config/BackendForm.php | 10 +++++ library/Graphite/Graphing/GraphingTrait.php | 1 + .../Graphite/Graphing/GraphiteWebClient.php | 40 +++++++++++++++++-- 3 files changed, 48 insertions(+), 3 deletions(-) diff --git a/application/forms/Config/BackendForm.php b/application/forms/Config/BackendForm.php index 90e0af2f..fb3970b7 100644 --- a/application/forms/Config/BackendForm.php +++ b/application/forms/Config/BackendForm.php @@ -53,6 +53,16 @@ public function createElements(array $formData) 'label' => $this->translate('Connect insecurely'), 'description' => $this->translate('Check this to not verify the remote\'s TLS certificate') ] + ], + [ + 'number', + 'graphite_timeout', + [ + 'label' => $this->translate('Request timeout'), + 'description' => $this->translate('The timeout for HTTP requests to Graphite Web'), + 'min' => 0, + 'placeholder' => 10 + ] ] ]); } diff --git a/library/Graphite/Graphing/GraphingTrait.php b/library/Graphite/Graphing/GraphingTrait.php index a1c1cdc2..463c61ca 100644 --- a/library/Graphite/Graphing/GraphingTrait.php +++ b/library/Graphite/Graphing/GraphingTrait.php @@ -73,6 +73,7 @@ public static function getMetricsDataSource() ->setUser($graphite->user) ->setPassword($graphite->password) ->setInsecure((bool) $graphite->insecure) + ->setTimeout(isset($graphite->timeout) ? intval($graphite->timeout) : 10) ); } diff --git a/library/Graphite/Graphing/GraphiteWebClient.php b/library/Graphite/Graphing/GraphiteWebClient.php index 982a2afe..9d8196ad 100644 --- a/library/Graphite/Graphing/GraphiteWebClient.php +++ b/library/Graphite/Graphing/GraphiteWebClient.php @@ -40,6 +40,13 @@ class GraphiteWebClient */ protected $insecure = false; + /** + * Timeout for every Graphite Web HTTP request + * + * @var ?int + */ + protected $timeout; + /** * HTTP client * @@ -79,9 +86,12 @@ public function request(Url $url, $method = 'GET', array $headers = [], $body = // TODO(ak): keep connections alive (TCP handshakes are a bit expensive and TLS handshakes are very expensive) return (string) $this->httpClient->send( new Request($method, $this->completeUrl($url)->getAbsoluteUrl(), $headers, $body), - ['curl' => [ - CURLOPT_SSL_VERIFYPEER => ! $this->insecure - ]] + [ + 'curl' => [ + CURLOPT_SSL_VERIFYPEER => ! $this->insecure + ], + 'timeout' => $this->timeout ?? 10 + ] )->getBody(); } @@ -195,4 +205,28 @@ public function setInsecure($insecure = true) return $this; } + + /** + * Get the HTTP request timeout + * + * @return ?int + */ + public function getTimeout(): ?int + { + return $this->timeout; + } + + /** + * Set the HTTP request timeout + * + * @param ?int $timeout + * + * @return $this + */ + public function setTimeout(?int $timeout): self + { + $this->timeout = $timeout; + + return $this; + } }