Skip to content

Commit 3c52ba6

Browse files
committed
Refactor OTLPMetricsClient to use ESQL with TS
1 parent e92aedc commit 3c52ba6

8 files changed

Lines changed: 184 additions & 149 deletions

File tree

README.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,15 @@ This module requires the frontend module:
88

99
- https://github.com/NETWAYS/icingaweb2-module-perfdatagraphs
1010

11+
## Known Issues
12+
13+
> Allowed memory size exhausted
14+
15+
Lower the `max_data_points` so that less data is returned or reduce the number of metrics being fetched via the `metrics_include/exclude` settings.
16+
1117
## Installation Requirements
1218

1319
* PHP version ≥ 8.0
1420
* Icinga2 ElasticsearchWriter or OTLPMetricsWriter
1521
* IcingaDB or IDO Database
16-
* Elasticsearch
22+
* Elasticsearch (OTLP requires at least Elasticsearch 9.2)

application/forms/PerfdataGraphsElasticsearchConfigForm.php

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,17 @@ public function createElements(array $formData)
7373
'description' => t('Skip the TLS verification'),
7474
'label' => t('Skip the TLS verification')
7575
]);
76+
77+
$this->addElement('number', 'elasticsearch_api_max_data_points', [
78+
'label' => t('The maximum numbers of datapoints each series returns'),
79+
'description' => t(' '),
80+
'description' => t(
81+
'The maximum numbers of datapoints each series returns.'
82+
. ' The module will use an aggregations query to downsample to this number.'
83+
),
84+
'required' => false,
85+
'placeholder' => 10000,
86+
]);
7687
}
7788

7889
public function addSubmitButton()
@@ -160,10 +171,7 @@ public static function validateFormData($form): array
160171
$password = $form->getValue('elasticsearch_api_password', '');
161172
$index = $form->getValue('elasticsearch_api_index', 'icinga2');
162173
$tlsVerify = (bool) $form->getValue('elasticsearch_api_tls_insecure', false);
163-
164-
// TODO: Not yet implemented
165-
$maxDataPoints = 10000;
166-
// $maxDataPoints = $form->getValue('elasticsearch_max_data_points', 10000);
174+
$maxDataPoints = (int) $form->getValue('elasticsearch_api_max_data_points', 5000);
167175

168176
$writer = $form->getValue('elasticsearch_icinga_writer', '');
169177

library/Perfdatagraphselasticsearch/Client/BaseClient.php

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,14 @@
2222
abstract class BaseClient
2323
{
2424
protected Transport $transport;
25-
26-
// TODO: Currently unused
2725
protected int $maxDataPoints;
2826

2927
/**
3028
* parseDuration parses the duration string from the frontend
3129
* into something we can use with the API (from parameter).
3230
*
3331
* @param string $duration ISO8601 Duration
34-
* @param string $now current time (used in testing)
32+
* @param DateTime $now current time (used in testing)
3533
* @return string
3634
*/
3735
public function parseDuration(\DateTime $now, string $duration): string
@@ -137,6 +135,28 @@ public function search(array $params = [])
137135
return $d;
138136
}
139137

138+
public function query(string $query = '')
139+
{
140+
$uri = '_query';
141+
$method = 'POST';
142+
143+
$body = Json::encode(['query' => $query]);
144+
145+
$req = new Request($method, $uri, [], $body);
146+
147+
$response = $this->transport->sendRequest($req);
148+
$responseBody = $response->getBody()->getContents();
149+
150+
try {
151+
$d = Json::decode($responseBody, true);
152+
} catch (JsonDecodeException $e) {
153+
Logger::error('Failed to decode response: %s', $e);
154+
return [];
155+
}
156+
157+
return $d;
158+
}
159+
140160
/**
141161
* status tests connectivity to the Elasticsearch cluster
142162
* @return array

library/Perfdatagraphselasticsearch/Client/ESInterface.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,6 @@ public function fetchMetrics(
1919
bool $isHostCheck,
2020
array $includeMetrics,
2121
array $excludeMetrics,
22+
int $checkInterval
2223
): PerfdataResponse;
2324
}

library/Perfdatagraphselasticsearch/Client/ElasticsearchClient.php

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@
1313
use Icinga\Application\Logger;
1414
use Icinga\Util\Json;
1515

16-
use GuzzleHttp\Client;
16+
use DateTime;
1717
use Exception;
18+
use GuzzleHttp\Client;
1819

1920
/**
2021
* ElasticsearchClient is used with with Icinga2 ElasticsearchWriter
@@ -63,7 +64,7 @@ public static function fromConfig(Config $moduleConfig = null): ESInterface
6364
'api_url' => 'http://localhost:9200',
6465
'api_index' => 'icinga2',
6566
'api_timeout' => 10,
66-
'api_max_data_points' => 10000,
67+
'api_max_data_points' => 5000,
6768
'api_username' => '',
6869
'api_password' => '',
6970
'api_tls_insecure' => false,
@@ -83,11 +84,11 @@ public static function fromConfig(Config $moduleConfig = null): ESInterface
8384
$baseURI = rtrim($moduleConfig->get('elasticsearch', 'api_url', $default['api_url']), '/');
8485
$index = rtrim($moduleConfig->get('elasticsearch', 'api_index', $default['api_index']), 'icinga2');
8586
$timeout = (int) $moduleConfig->get('elasticsearch', 'api_timeout', $default['api_timeout']);
86-
$maxDataPoints = (int) $moduleConfig->get('elasticsearch', 'api_max_data_points', $default['api_max_data_points']);
8787
$username = $moduleConfig->get('elasticsearch', 'api_username', $default['api_username']);
8888
$password = $moduleConfig->get('elasticsearch', 'api_password', $default['api_password']);
8989
// Hint: We use a "skip TLS" logic in the UI, but Guzzle uses "verify TLS"
9090
$tlsVerify = !(bool) $moduleConfig->get('elasticsearch', 'api_tls_insecure', $default['api_tls_insecure']);
91+
$maxDataPoints = (int) $moduleConfig->get('elasticsearch', 'api_max_data_points', $default['api_max_data_points']);
9192

9293
return new static($baseURI, $username, $password, $maxDataPoints, $timeout, $tlsVerify, $index);
9394
}
@@ -126,7 +127,11 @@ public function fetchMetrics(
126127
bool $isHostCheck,
127128
array $includeMetrics,
128129
array $excludeMetrics,
130+
int $checkInterval = 0
129131
): PerfdataResponse {
132+
$now = new DateTime();
133+
$from = $this->parseDuration($now, $from);
134+
130135
$params = [
131136
'size' => 2000,
132137
'sort' => '@timestamp:asc',

0 commit comments

Comments
 (0)