Skip to content

Commit e214f14

Browse files
committed
Updated lambda lookup tool
1 parent 647a5a4 commit e214f14

File tree

5 files changed

+128
-111
lines changed

5 files changed

+128
-111
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
analyze_workflow_execution,
2121
fetch_document_record,
2222
fetch_recent_records,
23-
lambda_lookup,
23+
retrieve_document_context,
2424
search_cloudwatch_logs,
2525
)
2626

@@ -52,7 +52,7 @@ def create_error_analyzer_agent(
5252
search_cloudwatch_logs,
5353
fetch_document_record,
5454
fetch_recent_records,
55-
lambda_lookup,
55+
retrieve_document_context,
5656
analyze_workflow_execution,
5757
analyze_document_trace,
5858
analyze_system_performance,

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
fetch_document_record,
1919
fetch_recent_records,
2020
)
21-
from .lambda_tool import lambda_lookup
21+
from .lambda_tool import retrieve_document_context
2222
from .stepfunction_tool import analyze_workflow_execution
2323
from .xray_tool import (
2424
analyze_document_trace,
@@ -27,7 +27,7 @@
2727

2828
__all__ = [
2929
"search_cloudwatch_logs",
30-
"lambda_lookup",
30+
"retrieve_document_context",
3131
"fetch_document_record",
3232
"fetch_recent_records",
3333
"analyze_workflow_execution",

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ def fetch_document_record(object_key: str) -> Dict[str, Any]:
3838
- Verify document exists in the system
3939
4040
Tool chaining: If tracking_available=False, use search_cloudwatch_logs,
41-
xray_trace, or lambda_lookup for document analysis.
41+
xray_trace, or retrieve_document_context for document analysis.
4242
4343
Example usage:
4444
- "What's the status of report.pdf?"

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

Lines changed: 119 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,129 @@
1414
import boto3
1515
from strands import tool
1616

17-
from ..config import create_error_response, create_response
17+
from ..config import create_error_response
1818

1919
logger = logging.getLogger(__name__)
2020

2121

22+
@tool
23+
def retrieve_document_context(document_id: str) -> Dict[str, Any]:
24+
"""
25+
Retrieve comprehensive document processing context via Lambda lookup function.
26+
27+
Invokes the lookup Lambda function to gather execution context, timing information,
28+
and Step Function details for a specific document. Provides essential data for
29+
targeted error analysis and log searching.
30+
31+
Use this tool to:
32+
- Get complete document processing timeline and status
33+
- Extract Lambda request IDs for CloudWatch log correlation
34+
- Identify failed functions and execution context
35+
- Obtain precise processing time windows for analysis
36+
37+
Alternative: If you only need basic document metadata (status, timestamps, execution ARN)
38+
without detailed execution events and Lambda request IDs, consider using fetch_document_record
39+
which provides faster access to DynamoDB tracking data.
40+
41+
Example usage:
42+
- "Get processing context for report.pdf"
43+
- "Retrieve execution details for lending_package.pdf"
44+
- "Show me the processing timeline for document ABC123"
45+
- "Get Lambda request IDs for failed document processing"
46+
47+
Args:
48+
document_id: Document ObjectKey to analyze (e.g., "report.pdf", "lending_package.pdf")
49+
50+
Returns:
51+
Dict containing document context, execution details, and timing information
52+
"""
53+
try:
54+
lambda_client = boto3.client("lambda")
55+
function_name = get_lookup_function_name()
56+
57+
logger.info(
58+
f"Invoking lookup function: {function_name} for document: {document_id}"
59+
)
60+
61+
# Invoke lookup function
62+
response = lambda_client.invoke(
63+
FunctionName=function_name,
64+
InvocationType="RequestResponse",
65+
Payload=json.dumps({"object_key": document_id}),
66+
)
67+
68+
# Parse response
69+
payload = json.loads(response["Payload"].read().decode("utf-8"))
70+
71+
if payload.get("status") == "NOT_FOUND":
72+
return create_error_response(
73+
"Document not found in tracking database",
74+
document_found=False,
75+
document_id=document_id,
76+
)
77+
78+
if payload.get("status") == "ERROR":
79+
return create_error_response(
80+
payload.get("message", "Unknown error from lookup function"),
81+
document_found=False,
82+
document_id=document_id,
83+
)
84+
85+
# Extract execution context
86+
processing_detail = payload.get("processingDetail", {})
87+
execution_arn = processing_detail.get("executionArn")
88+
execution_events = processing_detail.get("events", [])
89+
90+
# Extract Lambda request IDs and function mapping from execution events
91+
request_context = extract_lambda_request_ids(execution_events)
92+
request_ids = request_context.get("all_request_ids", [])
93+
function_request_map = request_context.get("function_request_map", {})
94+
failed_functions = request_context.get("failed_functions", [])
95+
primary_failed_function = request_context.get("primary_failed_function")
96+
97+
# Get timestamps for precise time windows
98+
timestamps = payload.get("timing", {}).get("timestamps", {})
99+
100+
# Calculate processing time window
101+
start_time = None
102+
end_time = None
103+
104+
if timestamps.get("WorkflowStartTime"):
105+
start_time = datetime.fromisoformat(
106+
timestamps["WorkflowStartTime"].replace("Z", "+00:00")
107+
)
108+
109+
if timestamps.get("CompletionTime"):
110+
end_time = datetime.fromisoformat(
111+
timestamps["CompletionTime"].replace("Z", "+00:00")
112+
)
113+
114+
response = {
115+
"document_found": True,
116+
"document_id": document_id,
117+
"document_status": payload.get("status"),
118+
"execution_arn": execution_arn,
119+
"lambda_request_ids": request_ids,
120+
"function_request_map": function_request_map,
121+
"failed_functions": failed_functions,
122+
"primary_failed_function": primary_failed_function,
123+
"timestamps": timestamps,
124+
"processing_start_time": start_time,
125+
"processing_end_time": end_time,
126+
"execution_events_count": len(execution_events),
127+
"lookup_function_response": payload,
128+
}
129+
130+
logger.info(f"Document context response for {document_id}: {response}")
131+
return response
132+
133+
except Exception as e:
134+
logger.error(f"Error getting document context for {document_id}: {e}")
135+
return create_error_response(
136+
str(e), document_found=False, document_id=document_id
137+
)
138+
139+
22140
def get_lookup_function_name() -> str:
23141
"""
24142
Retrieve the Lambda lookup function name from environment configuration.
@@ -201,104 +319,3 @@ def _extract_request_id_from_string(text: str) -> Optional[str]:
201319
return matches[0]
202320

203321
return None
204-
205-
206-
@tool
207-
def lambda_lookup(document_id: str, stack_name: str = "") -> Dict[str, Any]:
208-
"""
209-
Retrieve comprehensive document processing context via Lambda lookup function.
210-
Invokes the lookup Lambda function to gather execution context, timing information,
211-
and Step Function details for a specific document. Provides essential data for
212-
targeted error analysis and log searching.
213-
214-
Args:
215-
document_id: Document ObjectKey to analyze
216-
stack_name: CloudFormation stack name (optional, for backward compatibility)
217-
218-
Returns:
219-
Dict containing document context, execution details, and timing information
220-
"""
221-
try:
222-
lambda_client = boto3.client("lambda")
223-
function_name = get_lookup_function_name()
224-
225-
logger.info(
226-
f"Invoking lookup function: {function_name} for document: {document_id}"
227-
)
228-
229-
# Invoke lookup function
230-
response = lambda_client.invoke(
231-
FunctionName=function_name,
232-
InvocationType="RequestResponse",
233-
Payload=json.dumps({"object_key": document_id}),
234-
)
235-
236-
# Parse response
237-
payload = json.loads(response["Payload"].read().decode("utf-8"))
238-
239-
if payload.get("status") == "NOT_FOUND":
240-
return create_error_response(
241-
"Document not found in tracking database",
242-
document_found=False,
243-
document_id=document_id,
244-
)
245-
246-
if payload.get("status") == "ERROR":
247-
return create_error_response(
248-
payload.get("message", "Unknown error from lookup function"),
249-
document_found=False,
250-
document_id=document_id,
251-
)
252-
253-
# Extract execution context
254-
processing_detail = payload.get("processingDetail", {})
255-
execution_arn = processing_detail.get("executionArn")
256-
execution_events = processing_detail.get("events", [])
257-
258-
# Extract Lambda request IDs and function mapping from execution events
259-
request_context = extract_lambda_request_ids(execution_events)
260-
request_ids = request_context.get("all_request_ids", [])
261-
function_request_map = request_context.get("function_request_map", {})
262-
failed_functions = request_context.get("failed_functions", [])
263-
primary_failed_function = request_context.get("primary_failed_function")
264-
265-
# Get timestamps for precise time windows
266-
timestamps = payload.get("timing", {}).get("timestamps", {})
267-
268-
# Calculate processing time window
269-
start_time = None
270-
end_time = None
271-
272-
if timestamps.get("WorkflowStartTime"):
273-
start_time = datetime.fromisoformat(
274-
timestamps["WorkflowStartTime"].replace("Z", "+00:00")
275-
)
276-
277-
if timestamps.get("CompletionTime"):
278-
end_time = datetime.fromisoformat(
279-
timestamps["CompletionTime"].replace("Z", "+00:00")
280-
)
281-
282-
return create_response(
283-
{
284-
"document_found": True,
285-
"document_id": document_id,
286-
"document_status": payload.get("status"),
287-
"execution_arn": execution_arn,
288-
"lambda_request_ids": request_ids,
289-
"function_request_map": function_request_map,
290-
"failed_functions": failed_functions,
291-
"primary_failed_function": primary_failed_function,
292-
"timestamps": timestamps,
293-
"processing_start_time": start_time,
294-
"processing_end_time": end_time,
295-
"execution_events_count": len(execution_events),
296-
"lookup_function_response": payload,
297-
}
298-
)
299-
300-
except Exception as e:
301-
logger.error(f"Error getting document context for {document_id}: {e}")
302-
return create_error_response(
303-
str(e), document_found=False, document_id=document_id
304-
)

lib/idp_common_pkg/tests/unit/agents/error_analyzer/test_tools.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,11 @@ def test_execution_context_tools_import(self):
3737
"""Test execution context tools can be imported."""
3838
from idp_common.agents.error_analyzer.tools import (
3939
analyze_workflow_execution,
40-
lambda_lookup,
40+
retrieve_document_context,
4141
)
4242

43-
assert lambda_lookup is not None
44-
assert callable(lambda_lookup)
43+
assert retrieve_document_context is not None
44+
assert callable(retrieve_document_context)
4545
assert analyze_workflow_execution is not None
4646
assert callable(analyze_workflow_execution)
4747

@@ -65,7 +65,7 @@ def test_all_tools_available(self):
6565
"search_cloudwatch_logs",
6666
"fetch_document_record",
6767
"fetch_recent_records",
68-
"lambda_lookup",
68+
"retrieve_document_context",
6969
"analyze_workflow_execution",
7070
"analyze_document_trace",
7171
"analyze_system_performance",

0 commit comments

Comments
 (0)