Skip to content
Merged
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
8 changes: 8 additions & 0 deletions charmcraft.yaml
Comment thread
sinapah marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,14 @@ config:
Otherwise, the value is set to the greater of the setpoint or 100,000.
Ref: https://prometheus.io/docs/prometheus/latest/feature_flags/#exemplars-storage
type: int
out_of_order_time_window:
default: "0s"
description: |
The time window within which out-of-order samples are accepted for ingestion.
Supported units: s, m, h (Prometheus duration format; "m" is minutes).
Set to "0s" to disable (default).
See https://prometheus.io/docs/prometheus/latest/configuration/configuration/#tsdb
type: string

actions:
validate-configuration:
Expand Down
13 changes: 12 additions & 1 deletion src/charm.py
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,10 @@ def _on_collect_unit_status(self, event: CollectStatusEvent):
if not is_valid_timespec(cast(str, retention_time)):
event.add_status(BlockedStatus(f"Invalid time spec : {retention_time}"))

out_of_order_time_window = self.model.config.get("out_of_order_time_window", "")
if not is_valid_timespec(cast(str, out_of_order_time_window)):
event.add_status(BlockedStatus(f"Invalid time spec : {out_of_order_time_window}"))

# "Push" statuses
for status in self._stored.status.values():
event.add_status(to_status(status))
Expand Down Expand Up @@ -1131,8 +1135,15 @@ def _generate_prometheus_config(self) -> bool:

web_config = self._web_config()

storage_config = {}
if self._exemplars:
prometheus_config["storage"] = {"exemplars": {"max_exemplars": self._exemplars}}
storage_config["exemplars"] = {"max_exemplars": self._exemplars}
if is_valid_timespec(
ooo := cast(str, self.model.config.get("out_of_order_time_window", ""))
):
storage_config.setdefault("tsdb", {})["out_of_order_time_window"] = ooo
if storage_config:
prometheus_config["storage"] = storage_config

if self.workload_tracing_endpoint:
prometheus_config["tracing"] = self._tracing_config()
Expand Down
21 changes: 20 additions & 1 deletion tests/unit/test_charm.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,26 @@ def test_invalid_metrics_retention_times_can_not_be_set(self, *unused):

@k8s_resource_multipatch
@patch("lightkube.core.client.GenericSyncClient")
@prom_multipatch
def test_valid_out_of_order_time_window_can_be_set(self, *unused):
acceptable = ["5m", "1h", "30s", "0s"]
for value in acceptable:
self.harness.update_config({"out_of_order_time_window": value})
container = self.harness.charm.unit.get_container(self.harness.charm._name)
config = yaml.safe_load(container.pull(PROMETHEUS_CONFIG))
self.assertEqual(
config.get("storage", {}).get("tsdb", {}).get("out_of_order_time_window"), value
)

@k8s_resource_multipatch
@patch("lightkube.core.client.GenericSyncClient")
def test_invalid_out_of_order_time_window_can_not_be_set(self, *unused):
self.harness.update_config({"out_of_order_time_window": "5min"})
container = self.harness.charm.unit.get_container(self.harness.charm._name)
config = yaml.safe_load(container.pull(PROMETHEUS_CONFIG))
self.assertIsNone(config.get("storage", {}).get("tsdb"))

@k8s_resource_multipatch
@patch("lightkube.core.client.GenericSyncClient")
def test_global_evaluation_interval_can_be_set(self, *unused):
evalint_config = {}
acceptable_units = ["y", "w", "d", "h", "m", "s"]
Expand Down
Loading