fix aggregate search
This commit is contained in:
@@ -57,6 +57,20 @@ class GraylogAggregateSource:
|
|||||||
def fetch_count(self, *, range_seconds: int = 300) -> dict[str, object]:
|
def fetch_count(self, *, range_seconds: int = 300) -> dict[str, object]:
|
||||||
status = self.client.probe()
|
status = self.client.probe()
|
||||||
variants: list[dict[str, object]] = [
|
variants: list[dict[str, object]] = [
|
||||||
|
{
|
||||||
|
"query": self.query,
|
||||||
|
"streams": [self.stream] if self.stream else [],
|
||||||
|
"range_seconds": max(1, int(range_seconds)),
|
||||||
|
"group_by": [],
|
||||||
|
"metrics": ["count()"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"query": self.query,
|
||||||
|
"streams": [self.stream] if self.stream else [],
|
||||||
|
"range_seconds": max(1, int(range_seconds)),
|
||||||
|
"group_by": [],
|
||||||
|
"metrics": ["count"],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"query": self.query,
|
"query": self.query,
|
||||||
"streams": [self.stream] if self.stream else [],
|
"streams": [self.stream] if self.stream else [],
|
||||||
@@ -64,6 +78,13 @@ class GraylogAggregateSource:
|
|||||||
"group_by": [],
|
"group_by": [],
|
||||||
"metrics": [{"function": "count"}],
|
"metrics": [{"function": "count"}],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"query": self.query,
|
||||||
|
"streams": [self.stream] if self.stream else [],
|
||||||
|
"range_seconds": max(1, int(range_seconds)),
|
||||||
|
"groups": [],
|
||||||
|
"series": ["count()"],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"query": self.query,
|
"query": self.query,
|
||||||
"streams": [self.stream] if self.stream else [],
|
"streams": [self.stream] if self.stream else [],
|
||||||
@@ -71,6 +92,12 @@ class GraylogAggregateSource:
|
|||||||
"groups": [],
|
"groups": [],
|
||||||
"series": [{"function": "count"}],
|
"series": [{"function": "count"}],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"query": self.query,
|
||||||
|
"streams": [self.stream] if self.stream else [],
|
||||||
|
"range_seconds": max(1, int(range_seconds)),
|
||||||
|
"limit": 1,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"query": self.query,
|
"query": self.query,
|
||||||
"streams": [self.stream] if self.stream else [],
|
"streams": [self.stream] if self.stream else [],
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ def _stream_coverage(runtime_values: dict[str, object], stream_profiles: dict[st
|
|||||||
"latest_event_time": str(status.get("latest_event_time", "")),
|
"latest_event_time": str(status.get("latest_event_time", "")),
|
||||||
"truncated": bool(status.get("truncated")),
|
"truncated": bool(status.get("truncated")),
|
||||||
"partial": bool(status.get("partial")),
|
"partial": bool(status.get("partial")),
|
||||||
"error": str(status.get("error", "")),
|
"error": str(status.get("error", "") or status.get("aggregate_error", "")),
|
||||||
"health": "not_enabled" if not enabled else "partial_fetch" if status.get("partial") else "missing_profile" if not profile else "no_events" if int(status.get("events_fetched", 0) or 0) == 0 else "learning" if total_fields and ready_fields < total_fields else "ready" if total_fields else "profile_needs_fields",
|
"health": "not_enabled" if not enabled else "partial_fetch" if status.get("partial") else "missing_profile" if not profile else "no_events" if int(status.get("events_fetched", 0) or 0) == 0 else "learning" if total_fields and ready_fields < total_fields else "ready" if total_fields else "profile_needs_fields",
|
||||||
})
|
})
|
||||||
return rows
|
return rows
|
||||||
@@ -171,7 +171,7 @@ def build_status(
|
|||||||
if truncated_streams:
|
if truncated_streams:
|
||||||
warnings.append(f"{len(truncated_streams)} stream(s) hit max_events_per_stream; high EPS means the analysis window is only partially sampled.")
|
warnings.append(f"{len(truncated_streams)} stream(s) hit max_events_per_stream; high EPS means the analysis window is only partially sampled.")
|
||||||
mcp_status = {
|
mcp_status = {
|
||||||
"status": "partial" if partial_streams else "connected",
|
"status": "partial" if partial_streams or aggregate_errors else "connected",
|
||||||
"streams": stream_statuses,
|
"streams": stream_statuses,
|
||||||
"events_fetched": len(events),
|
"events_fetched": len(events),
|
||||||
"raw_events_fetched": len(events),
|
"raw_events_fetched": len(events),
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ class GraylogAggregateTests(unittest.TestCase):
|
|||||||
self.assertEqual(status["aggregate_status"], "ok")
|
self.assertEqual(status["aggregate_status"], "ok")
|
||||||
self.assertEqual(status["aggregate_events"], 12345)
|
self.assertEqual(status["aggregate_events"], 12345)
|
||||||
self.assertEqual(client.arguments[0]["streams"], ["firewall"])
|
self.assertEqual(client.arguments[0]["streams"], ["firewall"])
|
||||||
|
self.assertEqual(client.arguments[0]["metrics"], ["count()"])
|
||||||
|
|
||||||
def test_tries_fallback_argument_shape_after_tool_error(self):
|
def test_tries_fallback_argument_shape_after_tool_error(self):
|
||||||
client = _AggregateClient([
|
client = _AggregateClient([
|
||||||
|
|||||||
Reference in New Issue
Block a user