Skip to content

Commit 9431ac2

Browse files
authored
ROB-858 holmes telemetry (#330)
1 parent bed9d1f commit 9431ac2

File tree

6 files changed

+138
-2
lines changed

6 files changed

+138
-2
lines changed

holmes/clients/robusta_client.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import logging
2+
from typing import Optional
3+
import requests
4+
from pydantic import BaseModel, ConfigDict
5+
from holmes.common.env_vars import ROBUSTA_API_ENDPOINT
6+
7+
HOLMES_GET_INFO_URL = f"{ROBUSTA_API_ENDPOINT}/api/holmes/get_info"
8+
TIMEOUT = 2
9+
10+
11+
class HolmesInfo(BaseModel):
12+
model_config = ConfigDict(extra="ignore")
13+
latest_version: Optional[str] = None
14+
15+
16+
def fetch_holmes_info() -> Optional[HolmesInfo]:
17+
try:
18+
response = requests.get(HOLMES_GET_INFO_URL, timeout=TIMEOUT)
19+
response.raise_for_status()
20+
result = response.json()
21+
return HolmesInfo(**result)
22+
except Exception:
23+
logging.info("Failed to fetch holmes info")
24+
return None

holmes/config.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
import os.path
55
from typing import Any, Dict, List, Optional, Union
66

7+
from holmes import get_version
8+
from holmes.clients.robusta_client import HolmesInfo, fetch_holmes_info
79
from holmes.core.llm import LLM, DefaultLLM
810
from pydantic import FilePath, SecretStr
911
from pydash.arrays import concat
@@ -211,6 +213,28 @@ class Config(RobustaBaseConfig):
211213

212214
_server_tool_executor: Optional[ToolExecutor] = None
213215

216+
_version: Optional[str] = None
217+
_holmes_info: Optional[HolmesInfo] = None
218+
219+
@property
220+
def is_latest_version(self) -> bool:
221+
if self._holmes_info and self._holmes_info.latest_version:
222+
return self._version.startswith(self._holmes_info.latest_version)
223+
224+
# We couldn't resolve version, assume we are running the latest version
225+
return True
226+
227+
def model_post_init(self, __context: Any) -> None:
228+
self._version = get_version()
229+
self._holmes_info = fetch_holmes_info()
230+
231+
if not self.is_latest_version:
232+
logging.warning(
233+
"You are running version %s of holmes, but the latest version is %s. Please update to the latest version.",
234+
self._version,
235+
self._holmes_info.latest_version,
236+
)
237+
214238
@classmethod
215239
def load_from_env(cls):
216240
kwargs = {}

holmes/main.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,10 +287,14 @@ def ask(
287287
slack_token=slack_token,
288288
slack_channel=slack_channel,
289289
)
290-
system_prompt = load_and_render_prompt(system_prompt)
290+
291291
ai = config.create_console_toolcalling_llm(
292292
allowed_toolsets=allowed_toolsets, dal=None
293293
)
294+
template_context = {
295+
"enabled_toolsets": ai.tool_executor.enabled_toolsets_names,
296+
}
297+
system_prompt = load_and_render_prompt(system_prompt, template_context)
294298
if echo_request:
295299
console.print("[bold yellow]User:[/bold yellow] " + prompt)
296300
for path in include_file:

poetry.lock

Lines changed: 32 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ ruff = "^0.7.3"
5252
braintrust = "^0.0.168"
5353
autoevals = "^0.0.103"
5454
pre-commit = "^4.0.1"
55+
responses = "^0.23.1"
5556

5657
[build-system]
5758
requires = ["poetry-core"]
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
from http import HTTPStatus
2+
from unittest import mock
3+
from holmes.config import Config
4+
import responses
5+
6+
7+
@responses.activate
8+
def test_config_load_version_matches_latest():
9+
with mock.patch("holmes.config.get_version", return_value="1.0.0"):
10+
responses.add(
11+
responses.GET,
12+
"https://api.robusta.dev/api/holmes/get_info",
13+
json={"latest_version": "1.0.0"},
14+
)
15+
config = Config.load_from_env()
16+
assert config.is_latest_version
17+
18+
19+
@responses.activate
20+
def test_config_load_version_matches_latest_on_branch():
21+
with mock.patch("holmes.config.get_version", return_value="1.0.0-dev"):
22+
responses.add(
23+
responses.GET,
24+
"https://api.robusta.dev/api/holmes/get_info",
25+
json={"latest_version": "1.0.0"},
26+
)
27+
config = Config.load_from_env()
28+
assert config.is_latest_version
29+
30+
31+
@responses.activate
32+
def test_config_load_version_old():
33+
with mock.patch("holmes.config.get_version", return_value="0.9.0"):
34+
responses.add(
35+
responses.GET,
36+
"https://api.robusta.dev/api/holmes/get_info",
37+
json={"latest_version": "1.0.0"},
38+
)
39+
config = Config.load_from_env()
40+
assert not config.is_latest_version
41+
42+
43+
@responses.activate
44+
def test_config_load_failed_fetch_version():
45+
responses.add(
46+
responses.GET,
47+
"https://api.robusta.dev/api/holmes/get_info",
48+
status=HTTPStatus.INTERNAL_SERVER_ERROR,
49+
)
50+
config = Config.load_from_env()
51+
assert config._holmes_info is None
52+
assert config.is_latest_version

0 commit comments

Comments
 (0)