From c960b6084476df09d3a9034ab53d84c945a1f941 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 20 Aug 2026 13:38:59 +0000 Subject: [PATCH 1/2] Cache node IP lookups for prometheus alerts Replace the per-alert full NodeList scan (and its per-node log line) with a 15-minute TTL ip->node-name cache, refreshed only on expiry or cache miss. --- .../integrations/prometheus/trigger.py | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/src/robusta/integrations/prometheus/trigger.py b/src/robusta/integrations/prometheus/trigger.py index 79e1f450a..693273c4d 100644 --- a/src/robusta/integrations/prometheus/trigger.py +++ b/src/robusta/integrations/prometheus/trigger.py @@ -1,4 +1,5 @@ import logging +import time from typing import Any, Dict, List, NamedTuple, Optional, Type, Union from hikaru.model.rel_1_26 import DaemonSet, HorizontalPodAutoscaler, Job, Node, NodeList, StatefulSet @@ -129,16 +130,28 @@ class PrometheusAlertTriggers(BaseModel): on_prometheus_alert: Optional[PrometheusAlertTrigger] +NODE_IP_CACHE_TTL_SEC = 15 * 60 + + class AlertEventBuilder: + _node_name_by_ip: Dict[str, str] = {} + _node_ip_cache_time: float = 0 + @classmethod - def __find_node_by_ip(cls, ip) -> Optional[Node]: + def __refresh_node_ip_cache(cls): nodes: NodeList = NodeList.listNode().obj - for node in nodes.items: - addresses = [a.address for a in node.status.addresses] - logging.info(f"node {node.metadata.name} has addresses {addresses}") - if ip in addresses: - return node - return None + cls._node_name_by_ip = { + address.address: node.metadata.name for node in nodes.items for address in node.status.addresses + } + cls._node_ip_cache_time = time.time() + + @classmethod + def __find_node_by_ip(cls, ip) -> Optional[Node]: + cache_expired = time.time() - cls._node_ip_cache_time > NODE_IP_CACHE_TTL_SEC + if cache_expired or ip not in cls._node_name_by_ip: + cls.__refresh_node_ip_cache() + node_name = cls._node_name_by_ip.get(ip) + return Node().read(name=node_name) if node_name else None @classmethod def __load_node(cls, alert: PrometheusAlert, node_name: str) -> Optional[Node]: From fac0196a581b19b4c562ee824a5b185843986150 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 23 Aug 2026 06:54:51 +0000 Subject: [PATCH 2/2] Make node IP cache TTL configurable via NODE_IP_CACHE_TTL_SEC --- src/robusta/core/model/env_vars.py | 2 ++ src/robusta/integrations/prometheus/trigger.py | 4 +--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/robusta/core/model/env_vars.py b/src/robusta/core/model/env_vars.py index 2f3fcbca2..d7260b7a7 100644 --- a/src/robusta/core/model/env_vars.py +++ b/src/robusta/core/model/env_vars.py @@ -136,6 +136,8 @@ def load_bool(env_var, default: bool): NAMESPACE_DATA_TTL = int(os.environ.get("NAMESPACE_DATA_TTL", 30 * 60)) # in seconds +NODE_IP_CACHE_TTL_SEC = int(os.environ.get("NODE_IP_CACHE_TTL_SEC", 15 * 60)) + PROCESSED_ALERTS_CACHE_TTL = int(os.environ.get("PROCESSED_ALERT_CACHE_TTL", 2 * 3600)) PROCESSED_ALERTS_CACHE_MAX_SIZE = int(os.environ.get("PROCESSED_ALERTS_CACHE_MAX_SIZE", 100_000)) diff --git a/src/robusta/integrations/prometheus/trigger.py b/src/robusta/integrations/prometheus/trigger.py index 693273c4d..f79ef4cad 100644 --- a/src/robusta/integrations/prometheus/trigger.py +++ b/src/robusta/integrations/prometheus/trigger.py @@ -5,6 +5,7 @@ from hikaru.model.rel_1_26 import DaemonSet, HorizontalPodAutoscaler, Job, Node, NodeList, StatefulSet from pydantic.main import BaseModel +from robusta.core.model.env_vars import NODE_IP_CACHE_TTL_SEC from robusta.core.model.events import ExecutionBaseEvent from robusta.core.playbooks.base_trigger import BaseTrigger, TriggerEvent from robusta.core.reporting.base import Finding @@ -130,9 +131,6 @@ class PrometheusAlertTriggers(BaseModel): on_prometheus_alert: Optional[PrometheusAlertTrigger] -NODE_IP_CACHE_TTL_SEC = 15 * 60 - - class AlertEventBuilder: _node_name_by_ip: Dict[str, str] = {} _node_ip_cache_time: float = 0