Skip to content

Commit 6796d84

Browse files
authored
Merge pull request #106 from kazmer97/fix/analyser-agent-config
Config access simplifications
2 parents 8e15f2b + f67801a commit 6796d84

File tree

36 files changed

+868
-810
lines changed

36 files changed

+868
-810
lines changed

lib/idp_common_pkg/idp_common/__init__.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,22 @@
22
# SPDX-License-Identifier: MIT-0
33

44
# Use true lazy loading for all submodules
5+
from typing import TYPE_CHECKING
6+
57
__version__ = "0.1.0"
68

79
# Cache for lazy-loaded submodules
810
_submodules = {}
911

12+
# Type hints are only evaluated during type checking, not at runtime
13+
if TYPE_CHECKING:
14+
from .config import get_config as get_config
15+
from .config.models import IDPConfig as IDPConfig
16+
from .models import Document as Document
17+
from .models import Page as Page
18+
from .models import Section as Section
19+
from .models import Status as Status
20+
1021

1122
def __getattr__(name):
1223
"""Lazy load submodules only when accessed"""
@@ -65,6 +76,7 @@ def __getattr__(name):
6576
"reporting",
6677
"agents",
6778
"get_config",
79+
"IDPConfig",
6880
"Document",
6981
"Page",
7082
"Section",

lib/idp_common_pkg/idp_common/agents/analytics/schema_provider.py

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from typing import Any, Dict, Generator, Optional
1010

1111
from idp_common.config import get_config
12+
from idp_common.config.models import IDPConfig
1213
from idp_common.config.schema_constants import (
1314
SCHEMA_DESCRIPTION,
1415
SCHEMA_ITEMS,
@@ -211,7 +212,7 @@ def get_evaluation_tables_description() -> str:
211212

212213

213214
def get_dynamic_document_sections_description(
214-
config: Optional[Dict[str, Any]] = None,
215+
config: Optional[IDPConfig] = None,
215216
) -> str:
216217
"""
217218
Generate deployment-specific description of document sections tables based on actual configuration.
@@ -224,10 +225,10 @@ def get_dynamic_document_sections_description(
224225
"""
225226
try:
226227
if config is None:
227-
config = get_config()
228+
config = get_config(as_model=True)
228229

229230
# Get document classes from config
230-
classes = config.get("classes", [])
231+
classes = config.classes
231232

232233
if not classes:
233234
logger.warning("No classes found in configuration")
@@ -251,7 +252,7 @@ def get_dynamic_document_sections_description(
251252
# Generate table list
252253
table_names = []
253254
for doc_class in classes:
254-
class_name = doc_class.get("name", "Unknown")
255+
class_name = doc_class.get(X_AWS_IDP_DOCUMENT_TYPE, "Unknown")
255256
# Apply exact table name transformation logic
256257
table_name = f"document_sections_{_get_table_suffix(class_name)}"
257258
table_names.append(table_name)
@@ -500,7 +501,7 @@ def _get_error_aware_fallback(
500501
"""
501502

502503

503-
def get_database_overview(config: Optional[Dict[str, Any]] = None) -> str:
504+
def get_database_overview(config: Optional[IDPConfig] = None) -> str:
504505
"""
505506
Get a fast, lightweight overview of available tables with brief descriptions.
506507
This is the first step in the two-step progressive disclosure system.
@@ -513,10 +514,10 @@ def get_database_overview(config: Optional[Dict[str, Any]] = None) -> str:
513514
"""
514515
try:
515516
if config is None:
516-
config = get_config()
517+
config = get_config(as_model=True)
517518

518519
# Get document classes from config
519-
classes = config.get("classes", [])
520+
classes = config.classes
520521

521522
overview = """# Database Overview - Available Tables
522523
@@ -570,9 +571,7 @@ def get_database_overview(config: Optional[Dict[str, Any]] = None) -> str:
570571
return """# Database Overview - Error Loading Configuration"""
571572

572573

573-
def get_table_info(
574-
table_names: list[str], config: Optional[Dict[str, Any]] = None
575-
) -> str:
574+
def get_table_info(table_names: list[str], config: Optional[IDPConfig] = None) -> str:
576575
"""
577576
Get detailed schema information for specific tables.
578577
This is the second step in the two-step progressive disclosure system.
@@ -620,7 +619,7 @@ def get_table_info(
620619

621620

622621
def _get_specific_document_sections_table_info(
623-
table_suffix: str, config: Optional[Dict[str, Any]] = None
622+
table_suffix: str, config: Optional[IDPConfig] = None
624623
) -> str:
625624
"""
626625
Get detailed information for a specific document sections table.
@@ -634,9 +633,9 @@ def _get_specific_document_sections_table_info(
634633
"""
635634
try:
636635
if config is None:
637-
config = get_config()
636+
config = get_config(as_model=True)
638637

639-
classes = config.get("classes", [])
638+
classes = config.classes
640639
table_name = f"document_sections_{table_suffix}"
641640

642641
# Find the matching class for this table

lib/idp_common_pkg/idp_common/agents/error_analyzer/agent.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,14 @@
66
"""
77

88
import logging
9-
from typing import Any, Dict
9+
from typing import Optional
1010

1111
import boto3
1212
import strands
1313

14+
from idp_common.config import get_config
15+
1416
from ..common.strands_bedrock_model import create_strands_bedrock_model
15-
from .config import get_error_analyzer_config
1617
from .tools import (
1718
cloudwatch_document_logs,
1819
cloudwatch_logs,
@@ -29,9 +30,7 @@
2930

3031

3132
def create_error_analyzer_agent(
32-
config: Dict[str, Any] = None,
33-
session: boto3.Session = None,
34-
pattern_config: Dict[str, Any] = None,
33+
session: Optional[boto3.Session] = None,
3534
**kwargs,
3635
) -> strands.Agent:
3736
"""
@@ -44,7 +43,7 @@ def create_error_analyzer_agent(
4443
pattern_config: Pattern configuration containing agents section
4544
**kwargs: Additional arguments
4645
"""
47-
config = get_error_analyzer_config(pattern_config)
46+
config = get_config(as_model=True)
4847

4948
# Create session if not provided
5049
if session is None:
@@ -63,9 +62,11 @@ def create_error_analyzer_agent(
6362
xray_performance_analysis,
6463
]
6564
bedrock_model = create_strands_bedrock_model(
66-
model_id=config["model_id"], boto_session=session
65+
model_id=config.agents.error_analyzer.model_id, boto_session=session
6766
)
6867

6968
return strands.Agent(
70-
tools=tools, system_prompt=config["system_prompt"], model=bedrock_model
69+
tools=tools,
70+
system_prompt=config.agents.error_analyzer.system_prompt,
71+
model=bedrock_model,
7172
)

lib/idp_common_pkg/idp_common/agents/error_analyzer/config.py

Lines changed: 1 addition & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -6,99 +6,11 @@
66
"""
77

88
import logging
9-
from typing import Any, Dict, List
10-
11-
from ..common.config import configure_logging, get_environment_config
9+
from typing import Any, Dict
1210

1311
logger = logging.getLogger(__name__)
1412

1513

16-
def get_error_analyzer_config(pattern_config: Dict[str, Any] = None) -> Dict[str, Any]:
17-
"""
18-
Builds complete error analyzer configuration from environment and patterns.
19-
Get error analyzer configuration with defaults and overrides.
20-
21-
Returns:
22-
Dict containing complete error analyzer configuration
23-
"""
24-
from ... import get_config
25-
26-
# Start with base environment and context limits
27-
config = get_environment_config(["CLOUDWATCH_LOG_GROUP_PREFIX", "AWS_STACK_NAME"])
28-
config.update(get_context_limits())
29-
30-
# Load and apply agent configuration
31-
full_config = get_config()
32-
agent_config = full_config.get("agents", {}).get("error_analyzer", {})
33-
34-
if not agent_config:
35-
raise ValueError("error_analyzer configuration not found")
36-
37-
# Apply agent settings with defaults
38-
config.update(
39-
{
40-
"model_id": agent_config.get(
41-
"model_id", "anthropic.claude-3-sonnet-20240229-v1:0"
42-
),
43-
"system_prompt": agent_config.get("system_prompt"),
44-
"error_patterns": get_default_error_patterns(),
45-
"aws_capabilities": get_aws_service_capabilities(),
46-
}
47-
)
48-
49-
# Apply parameters with type conversion
50-
params = agent_config.get("parameters", {})
51-
config["max_log_events"] = safe_int_conversion(params.get("max_log_events"), 5)
52-
config["time_range_hours_default"] = safe_int_conversion(
53-
params.get("time_range_hours_default"), 24
54-
)
55-
56-
# Apply UI overrides for context limits - UI config takes precedence
57-
if pattern_config and "max_log_events" in pattern_config:
58-
config["max_log_events"] = safe_int_conversion(
59-
pattern_config["max_log_events"], config["max_log_events"]
60-
)
61-
62-
# Validate required fields
63-
if not config.get("system_prompt"):
64-
raise ValueError("system_prompt is required")
65-
66-
configure_logging(
67-
log_level=config.get("log_level"),
68-
strands_log_level=config.get("strands_log_level"),
69-
)
70-
71-
return config
72-
73-
74-
def get_default_error_patterns() -> List[str]:
75-
"""Returns standard error patterns for CloudWatch log filtering."""
76-
return [
77-
"ERROR",
78-
"CRITICAL",
79-
"FATAL",
80-
"Exception",
81-
"Traceback",
82-
"Failed",
83-
"Timeout",
84-
"AccessDenied",
85-
"ThrottlingException",
86-
]
87-
88-
89-
def get_context_limits() -> Dict[str, int]:
90-
"""Returns default resource and context size constraints."""
91-
return {
92-
"max_log_events": 5,
93-
"max_log_message_length": 400,
94-
"max_events_per_log_group": 5,
95-
"max_log_groups": 20,
96-
"max_stepfunction_timeline_events": 3,
97-
"max_stepfunction_error_length": 400,
98-
"time_range_hours_default": 24,
99-
}
100-
101-
10214
def get_aws_service_capabilities() -> Dict[str, Any]:
10315
"""Returns AWS service integration metadata and descriptions."""
10416
return {
@@ -161,12 +73,3 @@ def truncate_message(message: str, max_length: int = 200) -> str:
16173
if len(message) <= max_length:
16274
return message
16375
return message[:max_length] + "... [truncated]"
164-
165-
166-
def get_config_with_fallback() -> Dict[str, Any]:
167-
"""Gets error analyzer config with graceful fallback to defaults."""
168-
try:
169-
return get_error_analyzer_config()
170-
except Exception as e:
171-
logger.warning(f"Failed to load config, using defaults: {e}")
172-
return get_context_limits()

lib/idp_common_pkg/idp_common/agents/error_analyzer/tools/stepfunction_tool.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,11 @@
1111
import boto3
1212
from strands import tool
1313

14+
from idp_common.config import get_config
15+
1416
from ..config import (
1517
create_error_response,
1618
create_response,
17-
get_config_with_fallback,
1819
)
1920

2021
logger = logging.getLogger(__name__)
@@ -98,8 +99,11 @@ def _analyze_execution_timeline(events: List[Dict[str, Any]]) -> Dict[str, Any]:
9899
return {"error": "No execution events available"}
99100

100101
# Cache config values once
101-
config = get_config_with_fallback()
102-
max_timeline_events = config.get("max_stepfunction_timeline_events", 3)
102+
config = get_config(as_model=True)
103+
104+
max_timeline_events = (
105+
config.agents.error_analyzer.parameters.max_stepfunction_timeline_events
106+
)
103107

104108
timeline = []
105109
failure_point = None

lib/idp_common_pkg/idp_common/agents/error_analyzer/tools/xray_tool.py

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,11 @@
1313
import boto3
1414
from strands import tool
1515

16+
from idp_common.config import get_config
17+
1618
from ..config import (
1719
create_error_response,
1820
create_response,
19-
get_config_with_fallback,
2021
safe_int_conversion,
2122
)
2223

@@ -81,8 +82,10 @@ def _analyze_trace_segments(segments: List[Dict[str, Any]]) -> Dict[str, Any]:
8182
error_segments = []
8283
slow_segments = []
8384

84-
config = get_config_with_fallback()
85-
slow_threshold = config.get("xray_slow_segment_threshold_ms", 5000)
85+
config = get_config(as_model=True)
86+
slow_threshold = (
87+
config.agents.error_analyzer.parameters.xray_slow_segment_threshold_ms
88+
)
8689

8790
for segment in segments:
8891
segment_doc = _parse_segment_document(segment.get("Document", {}))
@@ -338,9 +341,13 @@ def _analyze_service_performance(
338341
if not services:
339342
return {"services_found": 0, "message": "No service map data available"}
340343

341-
config = get_config_with_fallback()
342-
error_rate_threshold = config.get("xray_error_rate_threshold", 0.05)
343-
response_time_threshold = config.get("xray_response_time_threshold_ms", 10000)
344+
config = get_config(as_model=True)
345+
error_rate_threshold = (
346+
config.agents.error_analyzer.parameters.xray_error_rate_threshold
347+
)
348+
response_time_threshold = (
349+
config.agents.error_analyzer.parameters.xray_response_time_threshold_ms
350+
)
344351

345352
service_analysis = []
346353
high_error_services = []

0 commit comments

Comments
 (0)