ragaai-catalyst 2.2.4.1b1__py3-none-any.whl → 2.2.4.1b3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ragaai_catalyst/tracers/agentic_tracing/upload/trace_uploader.py +34 -122
- ragaai_catalyst/tracers/agentic_tracing/upload/upload_agentic_traces.py +48 -45
- ragaai_catalyst/tracers/agentic_tracing/upload/upload_code.py +42 -79
- ragaai_catalyst/tracers/exporters/ragaai_trace_exporter.py +40 -15
- ragaai_catalyst/tracers/tracer.py +23 -1
- {ragaai_catalyst-2.2.4.1b1.dist-info → ragaai_catalyst-2.2.4.1b3.dist-info}/METADATA +1 -1
- {ragaai_catalyst-2.2.4.1b1.dist-info → ragaai_catalyst-2.2.4.1b3.dist-info}/RECORD +10 -11
- ragaai_catalyst/tracers/agentic_tracing/upload/session_manager.py +0 -92
- {ragaai_catalyst-2.2.4.1b1.dist-info → ragaai_catalyst-2.2.4.1b3.dist-info}/WHEEL +0 -0
- {ragaai_catalyst-2.2.4.1b1.dist-info → ragaai_catalyst-2.2.4.1b3.dist-info}/licenses/LICENSE +0 -0
- {ragaai_catalyst-2.2.4.1b1.dist-info → ragaai_catalyst-2.2.4.1b3.dist-info}/top_level.txt +0 -0
@@ -22,7 +22,6 @@ from typing import Dict, Any, Optional
|
|
22
22
|
import threading
|
23
23
|
import uuid
|
24
24
|
|
25
|
-
|
26
25
|
# Set up logging
|
27
26
|
log_dir = os.path.join(tempfile.gettempdir(), "ragaai_logs")
|
28
27
|
os.makedirs(log_dir, exist_ok=True)
|
@@ -50,13 +49,11 @@ try:
|
|
50
49
|
from ragaai_catalyst.tracers.agentic_tracing.upload.upload_code import upload_code
|
51
50
|
# from ragaai_catalyst.tracers.agentic_tracing.upload.upload_trace_metric import upload_trace_metric
|
52
51
|
from ragaai_catalyst.tracers.agentic_tracing.utils.create_dataset_schema import create_dataset_schema_with_trace
|
53
|
-
from ragaai_catalyst.tracers.agentic_tracing.upload.session_manager import session_manager
|
54
52
|
from ragaai_catalyst import RagaAICatalyst
|
55
53
|
IMPORTS_AVAILABLE = True
|
56
54
|
except ImportError:
|
57
55
|
logger.warning("RagaAI Catalyst imports not available - running in test mode")
|
58
56
|
IMPORTS_AVAILABLE = False
|
59
|
-
session_manager = None
|
60
57
|
|
61
58
|
# Define task queue directory
|
62
59
|
QUEUE_DIR = os.path.join(tempfile.gettempdir(), "ragaai_tasks")
|
@@ -75,10 +72,6 @@ _executor_lock = threading.Lock()
|
|
75
72
|
_futures: Dict[str, Any] = {}
|
76
73
|
_futures_lock = threading.Lock()
|
77
74
|
|
78
|
-
# Dataset creation cache to avoid redundant API calls
|
79
|
-
_dataset_cache: Dict[str, Dict[str, Any]] = {}
|
80
|
-
_dataset_cache_lock = threading.Lock()
|
81
|
-
DATASET_CACHE_DURATION = 600 # 10 minutes in seconds
|
82
75
|
|
83
76
|
_cleanup_lock = threading.Lock()
|
84
77
|
_last_cleanup = 0
|
@@ -95,7 +88,7 @@ def get_executor(max_workers=None):
|
|
95
88
|
if _executor is None:
|
96
89
|
# Calculate optimal worker count
|
97
90
|
if max_workers is None:
|
98
|
-
max_workers = min(
|
91
|
+
max_workers = min(32, (os.cpu_count() or 1) * 4)
|
99
92
|
|
100
93
|
logger.info(f"Creating ThreadPoolExecutor with {max_workers} workers")
|
101
94
|
_executor = concurrent.futures.ThreadPoolExecutor(
|
@@ -117,57 +110,9 @@ def generate_unique_task_id():
|
|
117
110
|
unique_id = str(uuid.uuid4())[:8] # Short UUID
|
118
111
|
return f"task_{int(time.time())}_{os.getpid()}_{counter}_{unique_id}"
|
119
112
|
|
120
|
-
def _generate_dataset_cache_key(dataset_name: str, project_name: str, base_url: str) -> str:
|
121
|
-
"""Generate a unique cache key for dataset creation"""
|
122
|
-
return f"{dataset_name}#{project_name}#{base_url}"
|
123
|
-
|
124
|
-
def _is_dataset_cached(cache_key: str) -> bool:
|
125
|
-
"""Check if dataset creation is cached and still valid"""
|
126
|
-
with _dataset_cache_lock:
|
127
|
-
if cache_key not in _dataset_cache:
|
128
|
-
return False
|
129
|
-
|
130
|
-
cache_entry = _dataset_cache[cache_key]
|
131
|
-
cache_time = cache_entry.get('timestamp', 0)
|
132
|
-
current_time = time.time()
|
133
|
-
|
134
|
-
# Check if cache is still valid (within 10 minutes)
|
135
|
-
if current_time - cache_time <= DATASET_CACHE_DURATION:
|
136
|
-
logger.info(f"Dataset creation cache hit for key: {cache_key}")
|
137
|
-
return True
|
138
|
-
else:
|
139
|
-
# Cache expired, remove it
|
140
|
-
logger.info(f"Dataset creation cache expired for key: {cache_key}")
|
141
|
-
del _dataset_cache[cache_key]
|
142
|
-
return False
|
143
|
-
|
144
|
-
def _cache_dataset_creation(cache_key: str, response: Any) -> None:
|
145
|
-
"""Cache successful dataset creation"""
|
146
|
-
with _dataset_cache_lock:
|
147
|
-
_dataset_cache[cache_key] = {
|
148
|
-
'timestamp': time.time(),
|
149
|
-
'response': response
|
150
|
-
}
|
151
|
-
|
152
|
-
def _cleanup_expired_cache_entries() -> None:
|
153
|
-
"""Remove expired cache entries"""
|
154
|
-
current_time = time.time()
|
155
|
-
with _dataset_cache_lock:
|
156
|
-
expired_keys = []
|
157
|
-
for cache_key, cache_entry in _dataset_cache.items():
|
158
|
-
cache_time = cache_entry.get('timestamp', 0)
|
159
|
-
if current_time - cache_time > DATASET_CACHE_DURATION:
|
160
|
-
expired_keys.append(cache_key)
|
161
|
-
|
162
|
-
for key in expired_keys:
|
163
|
-
del _dataset_cache[key]
|
164
|
-
|
165
|
-
if expired_keys:
|
166
|
-
logger.info(f"Cleaned up {len(expired_keys)} expired dataset cache entries")
|
167
|
-
|
168
113
|
def process_upload(task_id: str, filepath: str, hash_id: str, zip_path: str,
|
169
114
|
project_name: str, project_id: str, dataset_name: str,
|
170
|
-
user_details: Dict[str, Any], base_url: str,
|
115
|
+
user_details: Dict[str, Any], base_url: str, timeout=120, fail_on_trace_error=True) -> Dict[str, Any]:
|
171
116
|
"""
|
172
117
|
Process a single upload task
|
173
118
|
|
@@ -220,36 +165,20 @@ def process_upload(task_id: str, filepath: str, hash_id: str, zip_path: str,
|
|
220
165
|
save_task_status(result)
|
221
166
|
return result
|
222
167
|
|
223
|
-
# Step 1: Create dataset schema
|
168
|
+
# Step 1: Create dataset schema
|
224
169
|
logger.info(f"Creating dataset schema for {dataset_name} with base_url: {base_url} and timeout: {timeout}")
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
dataset_name=dataset_name,
|
238
|
-
project_name=project_name,
|
239
|
-
base_url=base_url,
|
240
|
-
user_details=user_details,
|
241
|
-
timeout=timeout
|
242
|
-
)
|
243
|
-
logger.info(f"Dataset schema created: {response}")
|
244
|
-
|
245
|
-
# Cache the response only if status code is 200
|
246
|
-
if response and hasattr(response, 'status_code') and response.status_code in [200, 201]:
|
247
|
-
_cache_dataset_creation(cache_key, response)
|
248
|
-
logger.info(f"Response cached successfully for dataset: {dataset_name} and key: {cache_key}")
|
249
|
-
|
250
|
-
except Exception as e:
|
251
|
-
logger.error(f"Error creating dataset schema: {e}")
|
252
|
-
# Continue with other steps
|
170
|
+
try:
|
171
|
+
response = create_dataset_schema_with_trace(
|
172
|
+
dataset_name=dataset_name,
|
173
|
+
project_name=project_name,
|
174
|
+
base_url=base_url,
|
175
|
+
user_details=user_details,
|
176
|
+
timeout=timeout
|
177
|
+
)
|
178
|
+
logger.info(f"Dataset schema created: {response}")
|
179
|
+
except Exception as e:
|
180
|
+
logger.error(f"Error creating dataset schema: {e}")
|
181
|
+
# Continue with other steps
|
253
182
|
|
254
183
|
# Step 2: Upload trace metrics
|
255
184
|
# if filepath and os.path.exists(filepath):
|
@@ -309,34 +238,28 @@ def process_upload(task_id: str, filepath: str, hash_id: str, zip_path: str,
|
|
309
238
|
logger.error(error_msg)
|
310
239
|
|
311
240
|
# Step 4: Upload code hash
|
312
|
-
if
|
313
|
-
logger.info(f"
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
logger.info(f"Code hash uploaded successfully: {response}")
|
330
|
-
except Exception as e:
|
331
|
-
logger.error(f"Error uploading code hash: {e}")
|
332
|
-
else:
|
333
|
-
logger.warning(f"Code zip {zip_path} not found, skipping code upload")
|
334
|
-
|
241
|
+
if hash_id and zip_path and os.path.exists(zip_path):
|
242
|
+
logger.info(f"Uploading code hash {hash_id} with base_url: {base_url} and timeout: {timeout}")
|
243
|
+
try:
|
244
|
+
response = upload_code(
|
245
|
+
hash_id=hash_id,
|
246
|
+
zip_path=zip_path,
|
247
|
+
project_name=project_name,
|
248
|
+
dataset_name=dataset_name,
|
249
|
+
base_url=base_url,
|
250
|
+
timeout=timeout
|
251
|
+
)
|
252
|
+
logger.info(f"Code hash uploaded: {response}")
|
253
|
+
except Exception as e:
|
254
|
+
logger.error(f"Error uploading code hash: {e}")
|
255
|
+
else:
|
256
|
+
logger.warning(f"Code zip {zip_path} not found, skipping code upload")
|
257
|
+
|
335
258
|
# Mark task as completed
|
336
259
|
result["status"] = STATUS_COMPLETED
|
337
260
|
result["end_time"] = datetime.now().isoformat()
|
338
261
|
logger.info(f"Task {task_id} completed successfully")
|
339
|
-
|
262
|
+
|
340
263
|
except Exception as e:
|
341
264
|
logger.error(f"Error processing task {task_id}: {e}")
|
342
265
|
result["status"] = STATUS_FAILED
|
@@ -379,8 +302,7 @@ def save_task_status(task_status: Dict[str, Any]):
|
|
379
302
|
with open(status_path, "w") as f:
|
380
303
|
json.dump(task_status, f, indent=2)
|
381
304
|
|
382
|
-
def submit_upload_task(filepath, hash_id, zip_path, project_name, project_id, dataset_name, user_details, base_url,
|
383
|
-
tracer_type, timeout=120):
|
305
|
+
def submit_upload_task(filepath, hash_id, zip_path, project_name, project_id, dataset_name, user_details, base_url, timeout=120):
|
384
306
|
"""
|
385
307
|
Submit a new upload task using futures.
|
386
308
|
|
@@ -427,7 +349,6 @@ def submit_upload_task(filepath, hash_id, zip_path, project_name, project_id, da
|
|
427
349
|
dataset_name=dataset_name,
|
428
350
|
user_details=user_details,
|
429
351
|
base_url=base_url,
|
430
|
-
tracer_type = tracer_type,
|
431
352
|
timeout=timeout,
|
432
353
|
fail_on_trace_error=True
|
433
354
|
)
|
@@ -458,7 +379,6 @@ def submit_upload_task(filepath, hash_id, zip_path, project_name, project_id, da
|
|
458
379
|
dataset_name=dataset_name,
|
459
380
|
user_details=user_details,
|
460
381
|
base_url=base_url,
|
461
|
-
tracer_type=tracer_type,
|
462
382
|
timeout=timeout,
|
463
383
|
fail_on_trace_error=True
|
464
384
|
)
|
@@ -630,14 +550,6 @@ def shutdown(timeout=120):
|
|
630
550
|
|
631
551
|
_executor = None
|
632
552
|
|
633
|
-
# Close the session manager to clean up HTTP connections
|
634
|
-
if session_manager is not None:
|
635
|
-
try:
|
636
|
-
session_manager.close()
|
637
|
-
logger.info("Session manager closed successfully")
|
638
|
-
except Exception as e:
|
639
|
-
logger.error(f"Error closing session manager: {e}")
|
640
|
-
|
641
553
|
# Register shutdown handler
|
642
554
|
atexit.register(shutdown)
|
643
555
|
|
@@ -4,13 +4,13 @@ import os
|
|
4
4
|
import re
|
5
5
|
import time
|
6
6
|
from urllib.parse import urlparse, urlunparse
|
7
|
-
from urllib3.exceptions import PoolError, MaxRetryError, NewConnectionError
|
8
|
-
from requests.exceptions import ConnectionError, Timeout, RequestException
|
9
|
-
from .session_manager import session_manager
|
10
7
|
|
11
8
|
import requests
|
12
9
|
|
13
10
|
logger = logging.getLogger(__name__)
|
11
|
+
logging_level = (
|
12
|
+
logger.setLevel(logging.DEBUG) if os.getenv("DEBUG") == "1" else logging.INFO
|
13
|
+
)
|
14
14
|
|
15
15
|
from ragaai_catalyst.ragaai_catalyst import RagaAICatalyst
|
16
16
|
|
@@ -47,36 +47,42 @@ class UploadAgenticTraces:
|
|
47
47
|
"X-Project-Name": self.project_name,
|
48
48
|
}
|
49
49
|
|
50
|
+
logger.debug("Started getting presigned url: ")
|
51
|
+
logger.debug(f"Payload: {payload}")
|
52
|
+
logger.debug(f"Headers: {headers}")
|
50
53
|
try:
|
51
54
|
start_time = time.time()
|
52
55
|
endpoint = f"{self.base_url}/v1/llm/presigned-url"
|
53
56
|
# Changed to POST from GET
|
54
|
-
response =
|
57
|
+
response = requests.request(
|
55
58
|
"POST", endpoint, headers=headers, data=payload, timeout=self.timeout
|
56
59
|
)
|
57
60
|
elapsed_ms = (time.time() - start_time) * 1000
|
58
61
|
logger.debug(
|
59
62
|
f"API Call: [POST] {endpoint} | Status: {response.status_code} | Time: {elapsed_ms:.2f}ms"
|
60
63
|
)
|
61
|
-
|
62
|
-
if response.status_code == 200:
|
64
|
+
if response.status_code in [200, 201]:
|
63
65
|
presignedURLs = response.json()["data"]["presignedUrls"][0]
|
66
|
+
logger.debug(f"Got presigned url: {presignedURLs}")
|
64
67
|
presignedurl = self.update_presigned_url(presignedURLs, self.base_url)
|
68
|
+
logger.debug(f"Updated presigned url: {presignedurl}")
|
65
69
|
return presignedurl
|
66
70
|
else:
|
67
71
|
# If POST fails, try GET
|
68
|
-
response =
|
72
|
+
response = requests.request(
|
69
73
|
"GET", endpoint, headers=headers, data=payload, timeout=self.timeout
|
70
74
|
)
|
71
75
|
elapsed_ms = (time.time() - start_time) * 1000
|
72
76
|
logger.debug(
|
73
77
|
f"API Call: [GET] {endpoint} | Status: {response.status_code} | Time: {elapsed_ms:.2f}ms"
|
74
78
|
)
|
75
|
-
if response.status_code
|
79
|
+
if response.status_code in [200, 201]:
|
76
80
|
presignedURLs = response.json()["data"]["presignedUrls"][0]
|
81
|
+
logger.debug(f"Got presigned url: {presignedURLs}")
|
77
82
|
presignedurl = self.update_presigned_url(
|
78
83
|
presignedURLs, self.base_url
|
79
84
|
)
|
85
|
+
logger.debug(f"Updated presigned url: {presignedurl}")
|
80
86
|
return presignedurl
|
81
87
|
elif response.status_code == 401:
|
82
88
|
logger.warning("Received 401 error. Attempting to refresh token.")
|
@@ -86,7 +92,7 @@ class UploadAgenticTraces:
|
|
86
92
|
"Authorization": f"Bearer {token}",
|
87
93
|
"X-Project-Name": self.project_name,
|
88
94
|
}
|
89
|
-
response =
|
95
|
+
response = requests.request(
|
90
96
|
"POST",
|
91
97
|
endpoint,
|
92
98
|
headers=headers,
|
@@ -97,11 +103,13 @@ class UploadAgenticTraces:
|
|
97
103
|
logger.debug(
|
98
104
|
f"API Call: [POST] {endpoint} | Status: {response.status_code} | Time: {elapsed_ms:.2f}ms"
|
99
105
|
)
|
100
|
-
if response.status_code
|
106
|
+
if response.status_code in [200, 201]:
|
101
107
|
presignedURLs = response.json()["data"]["presignedUrls"][0]
|
108
|
+
logger.debug(f"Got presigned url: {presignedURLs}")
|
102
109
|
presignedurl = self.update_presigned_url(
|
103
110
|
presignedURLs, self.base_url
|
104
111
|
)
|
112
|
+
logger.debug(f"Updated presigned url: {presignedurl}")
|
105
113
|
return presignedurl
|
106
114
|
else:
|
107
115
|
logger.error(
|
@@ -113,10 +121,8 @@ class UploadAgenticTraces:
|
|
113
121
|
f"Error while getting presigned url: {response.json()['message']}"
|
114
122
|
)
|
115
123
|
return None
|
116
|
-
|
117
|
-
|
118
|
-
return None
|
119
|
-
except RequestException as e:
|
124
|
+
|
125
|
+
except requests.exceptions.RequestException as e:
|
120
126
|
logger.error(f"Error while getting presigned url: {e}")
|
121
127
|
return None
|
122
128
|
|
@@ -143,16 +149,16 @@ class UploadAgenticTraces:
|
|
143
149
|
|
144
150
|
if "blob.core.windows.net" in presignedUrl: # Azure
|
145
151
|
headers["x-ms-blob-type"] = "BlockBlob"
|
146
|
-
|
152
|
+
print("Uploading agentic traces...")
|
147
153
|
try:
|
148
154
|
with open(filename) as f:
|
149
155
|
payload = f.read().replace("\n", "").replace("\r", "").encode()
|
150
156
|
except Exception as e:
|
151
|
-
|
157
|
+
print(f"Error while reading file: {e}")
|
152
158
|
return False
|
153
159
|
try:
|
154
160
|
start_time = time.time()
|
155
|
-
response =
|
161
|
+
response = requests.request(
|
156
162
|
"PUT", presignedUrl, headers=headers, data=payload, timeout=self.timeout
|
157
163
|
)
|
158
164
|
elapsed_ms = (time.time() - start_time) * 1000
|
@@ -162,11 +168,8 @@ class UploadAgenticTraces:
|
|
162
168
|
if response.status_code != 200 or response.status_code != 201:
|
163
169
|
return response, response.status_code
|
164
170
|
return True
|
165
|
-
except
|
166
|
-
|
167
|
-
return False
|
168
|
-
except RequestException as e:
|
169
|
-
logger.error(f"Error while uploading trace to presigned url: {e}")
|
171
|
+
except requests.exceptions.RequestException as e:
|
172
|
+
print(f"Error while uploading to presigned url: {e}")
|
170
173
|
return False
|
171
174
|
|
172
175
|
def insert_traces(self, presignedUrl):
|
@@ -182,18 +185,21 @@ class UploadAgenticTraces:
|
|
182
185
|
"datasetSpans": self._get_dataset_spans(), # Extra key for agentic traces
|
183
186
|
}
|
184
187
|
)
|
188
|
+
logger.debug(f"Inserting agentic traces to presigned url: {presignedUrl}")
|
185
189
|
try:
|
186
190
|
start_time = time.time()
|
187
191
|
endpoint = f"{self.base_url}/v1/llm/insert/trace"
|
188
|
-
response =
|
192
|
+
response = requests.request(
|
189
193
|
"POST", endpoint, headers=headers, data=payload, timeout=self.timeout
|
190
194
|
)
|
195
|
+
logger.debug(f"Payload: {payload}")
|
196
|
+
logger.debug(f"Headers: {headers}")
|
191
197
|
elapsed_ms = (time.time() - start_time) * 1000
|
192
198
|
logger.debug(
|
193
199
|
f"API Call: [POST] {endpoint} | Status: {response.status_code} | Time: {elapsed_ms:.2f}ms"
|
194
200
|
)
|
195
201
|
if response.status_code in [200, 201]:
|
196
|
-
logger.
|
202
|
+
logger.debug("Successfully inserted traces")
|
197
203
|
return True
|
198
204
|
elif response.status_code == 401:
|
199
205
|
logger.warning("Received 401 error. Attempting to refresh token.")
|
@@ -203,7 +209,7 @@ class UploadAgenticTraces:
|
|
203
209
|
"Content-Type": "application/json",
|
204
210
|
"X-Project-Name": self.project_name,
|
205
211
|
}
|
206
|
-
response =
|
212
|
+
response = requests.request(
|
207
213
|
"POST",
|
208
214
|
endpoint,
|
209
215
|
headers=headers,
|
@@ -215,27 +221,24 @@ class UploadAgenticTraces:
|
|
215
221
|
f"API Call: [POST] {endpoint} | Status: {response.status_code} | Time: {elapsed_ms:.2f}ms"
|
216
222
|
)
|
217
223
|
if response.status_code in [200, 201]:
|
218
|
-
logger.
|
224
|
+
logger.debug("Successfully inserted traces")
|
219
225
|
return True
|
220
226
|
else:
|
221
|
-
logger.
|
227
|
+
logger.debug("Error while inserting traces")
|
222
228
|
return False
|
223
229
|
else:
|
224
|
-
logger.
|
230
|
+
logger.debug("Error while inserting traces")
|
225
231
|
return False
|
226
|
-
except
|
227
|
-
|
228
|
-
return
|
229
|
-
except RequestException as e:
|
230
|
-
logger.error(f"Error while inserting traces: {e}")
|
231
|
-
return False
|
232
|
+
except requests.exceptions.RequestException as e:
|
233
|
+
logger.debug(f"Error while inserting traces: {e}")
|
234
|
+
return None
|
232
235
|
|
233
236
|
def _get_dataset_spans(self):
|
234
237
|
try:
|
235
238
|
with open(self.json_file_path) as f:
|
236
239
|
data = json.load(f)
|
237
240
|
except Exception as e:
|
238
|
-
|
241
|
+
logger.debug(f"Error while reading file: {e}")
|
239
242
|
return None
|
240
243
|
try:
|
241
244
|
spans = data["data"][0]["spans"]
|
@@ -257,41 +260,41 @@ class UploadAgenticTraces:
|
|
257
260
|
continue
|
258
261
|
return dataset_spans
|
259
262
|
except Exception as e:
|
260
|
-
logger.
|
263
|
+
logger.debug(f"Error while reading dataset spans: {e}")
|
261
264
|
return None
|
262
265
|
|
263
266
|
def upload_agentic_traces(self):
|
264
267
|
try:
|
265
268
|
presigned_url = self._get_presigned_url()
|
266
269
|
if presigned_url is None:
|
267
|
-
logger.
|
270
|
+
logger.debug("Warning: Failed to obtain presigned URL")
|
268
271
|
return False
|
269
272
|
|
270
273
|
# Upload the file using the presigned URL
|
271
274
|
upload_result = self._put_presigned_url(presigned_url, self.json_file_path)
|
272
275
|
if not upload_result:
|
273
|
-
logger.
|
276
|
+
logger.debug("Error: Failed to upload file to presigned URL")
|
274
277
|
return False
|
275
278
|
elif isinstance(upload_result, tuple):
|
276
279
|
response, status_code = upload_result
|
277
280
|
if status_code not in [200, 201]:
|
278
|
-
logger.
|
279
|
-
f"Error:
|
281
|
+
logger.debug(
|
282
|
+
f"Error: Upload failed with status code {status_code}: {response.text if hasattr(response, 'text') else 'Unknown error'}")
|
280
283
|
return False
|
281
284
|
# Insert trace records
|
282
285
|
insert_success = self.insert_traces(presigned_url)
|
283
286
|
if not insert_success:
|
284
|
-
|
287
|
+
logger.debug("Error: Failed to insert trace records")
|
285
288
|
return False
|
286
289
|
|
287
|
-
logger.
|
290
|
+
logger.debug("Successfully uploaded agentic traces")
|
288
291
|
return True
|
289
292
|
except FileNotFoundError:
|
290
|
-
logger.
|
293
|
+
logger.debug(f"Error: Trace file not found at {self.json_file_path}")
|
291
294
|
return False
|
292
295
|
except ConnectionError as e:
|
293
|
-
logger.
|
296
|
+
logger.debug(f"Error: Network connection failed while uploading traces: {e}")
|
294
297
|
return False
|
295
298
|
except Exception as e:
|
296
|
-
logger.
|
299
|
+
logger.debug(f"Error while uploading agentic traces: {e}")
|
297
300
|
return False
|
@@ -1,18 +1,15 @@
|
|
1
|
+
import json
|
1
2
|
import logging
|
2
3
|
import os
|
3
4
|
import time
|
4
|
-
import re
|
5
|
-
import json
|
6
|
-
from urllib.parse import urlparse, urlunparse
|
7
|
-
from urllib3.exceptions import PoolError, MaxRetryError, NewConnectionError
|
8
|
-
from requests.exceptions import ConnectionError, Timeout, RequestException
|
9
5
|
|
10
6
|
import requests
|
11
7
|
|
12
8
|
from ragaai_catalyst.ragaai_catalyst import RagaAICatalyst
|
13
|
-
from .session_manager import session_manager
|
14
9
|
|
15
10
|
logger = logging.getLogger(__name__)
|
11
|
+
import re
|
12
|
+
from urllib.parse import urlparse, urlunparse
|
16
13
|
|
17
14
|
|
18
15
|
def upload_code(
|
@@ -22,26 +19,11 @@ def upload_code(
|
|
22
19
|
project_name, dataset_name, base_url, timeout=timeout
|
23
20
|
)
|
24
21
|
|
25
|
-
# Handle None case during exceptions - do not proceed
|
26
|
-
if code_hashes_list is None:
|
27
|
-
logger.error("Failed to fetch existing code hashes, cannot proceed with upload")
|
28
|
-
return None
|
29
|
-
|
30
22
|
if hash_id not in code_hashes_list:
|
31
23
|
presigned_url = _fetch_presigned_url(
|
32
24
|
project_name, dataset_name, base_url, timeout=timeout
|
33
25
|
)
|
34
|
-
|
35
|
-
if presigned_url is None:
|
36
|
-
logger.error("Failed to fetch presigned URL, cannot proceed with upload")
|
37
|
-
return None
|
38
|
-
|
39
|
-
upload_result = _put_zip_presigned_url(project_name, presigned_url, zip_path, timeout=timeout)
|
40
|
-
|
41
|
-
# Handle upload failure
|
42
|
-
if upload_result is False or (isinstance(upload_result, tuple) and upload_result[1] not in [200, 201]):
|
43
|
-
logger.error("Failed to upload zip file")
|
44
|
-
return None
|
26
|
+
_put_zip_presigned_url(project_name, presigned_url, zip_path, timeout=timeout)
|
45
27
|
|
46
28
|
response = _insert_code(
|
47
29
|
dataset_name,
|
@@ -51,10 +33,6 @@ def upload_code(
|
|
51
33
|
base_url,
|
52
34
|
timeout=timeout,
|
53
35
|
)
|
54
|
-
# Handle None response from insert_code
|
55
|
-
if response is None:
|
56
|
-
logger.error("Failed to insert code metadata")
|
57
|
-
return None
|
58
36
|
return response
|
59
37
|
else:
|
60
38
|
return "Code already exists"
|
@@ -71,7 +49,7 @@ def _fetch_dataset_code_hashes(project_name, dataset_name, base_url=None, timeou
|
|
71
49
|
url_base = base_url if base_url is not None else RagaAICatalyst.BASE_URL
|
72
50
|
start_time = time.time()
|
73
51
|
endpoint = f"{url_base}/v2/llm/dataset/code?datasetName={dataset_name}"
|
74
|
-
response =
|
52
|
+
response = requests.request(
|
75
53
|
"GET", endpoint, headers=headers, data=payload, timeout=timeout
|
76
54
|
)
|
77
55
|
elapsed_ms = (time.time() - start_time) * 1000
|
@@ -79,7 +57,7 @@ def _fetch_dataset_code_hashes(project_name, dataset_name, base_url=None, timeou
|
|
79
57
|
f"API Call: [GET] {endpoint} | Status: {response.status_code} | Time: {elapsed_ms:.2f}ms"
|
80
58
|
)
|
81
59
|
|
82
|
-
if response.status_code
|
60
|
+
if response.status_code == 200:
|
83
61
|
return response.json()["data"]["codeHashes"]
|
84
62
|
elif response.status_code == 401:
|
85
63
|
logger.warning("Received 401 error. Attempting to refresh token.")
|
@@ -88,25 +66,22 @@ def _fetch_dataset_code_hashes(project_name, dataset_name, base_url=None, timeou
|
|
88
66
|
"Authorization": f"Bearer {os.getenv('RAGAAI_CATALYST_TOKEN')}",
|
89
67
|
"X-Project-Name": project_name,
|
90
68
|
}
|
91
|
-
response =
|
69
|
+
response = requests.request(
|
92
70
|
"GET", endpoint, headers=headers, data=payload, timeout=timeout
|
93
71
|
)
|
94
72
|
elapsed_ms = (time.time() - start_time) * 1000
|
95
|
-
logger.debug(
|
96
|
-
|
73
|
+
logger.debug(
|
74
|
+
f"API Call: [GET] {endpoint} | Status: {response.status_code} | Time: {elapsed_ms:.2f}ms"
|
75
|
+
)
|
76
|
+
if response.status_code == 200:
|
97
77
|
return response.json()["data"]["codeHashes"]
|
98
78
|
else:
|
99
|
-
logger.error(
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
return None
|
104
|
-
except (PoolError, MaxRetryError, NewConnectionError, ConnectionError, Timeout) as e:
|
105
|
-
session_manager.handle_request_exceptions(e, "fetching dataset code hashes")
|
106
|
-
return None
|
107
|
-
except RequestException as e:
|
79
|
+
logger.error(
|
80
|
+
f"Failed to fetch code hashes: {response.json()['message']}"
|
81
|
+
)
|
82
|
+
except requests.exceptions.RequestException as e:
|
108
83
|
logger.error(f"Failed to list datasets: {e}")
|
109
|
-
|
84
|
+
pass
|
110
85
|
|
111
86
|
|
112
87
|
def update_presigned_url(presigned_url, base_url):
|
@@ -181,7 +156,7 @@ def _fetch_presigned_url(project_name, dataset_name, base_url=None, timeout=120)
|
|
181
156
|
logger.debug(
|
182
157
|
f"API Call: [POST] {endpoint} | Status: {response.status_code} | Time: {elapsed_ms:.2f}ms"
|
183
158
|
)
|
184
|
-
if response.status_code
|
159
|
+
if response.status_code == 200:
|
185
160
|
presigned_url = response.json()["data"]["presignedUrls"][0]
|
186
161
|
presigned_url = update_presigned_url(presigned_url, url_base)
|
187
162
|
return presigned_url
|
@@ -193,10 +168,9 @@ def _fetch_presigned_url(project_name, dataset_name, base_url=None, timeout=120)
|
|
193
168
|
logger.error(
|
194
169
|
f"Failed to fetch code hashes: {response.json()['message']}"
|
195
170
|
)
|
196
|
-
return None
|
197
171
|
except requests.exceptions.RequestException as e:
|
198
172
|
logger.error(f"Failed to list datasets: {e}")
|
199
|
-
|
173
|
+
pass
|
200
174
|
|
201
175
|
|
202
176
|
def _put_zip_presigned_url(project_name, presignedUrl, filename, timeout=120):
|
@@ -207,28 +181,21 @@ def _put_zip_presigned_url(project_name, presignedUrl, filename, timeout=120):
|
|
207
181
|
|
208
182
|
if "blob.core.windows.net" in presignedUrl: # Azure
|
209
183
|
headers["x-ms-blob-type"] = "BlockBlob"
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
184
|
+
print("Uploading code...")
|
185
|
+
with open(filename, "rb") as f:
|
186
|
+
payload = f.read()
|
187
|
+
|
188
|
+
start_time = time.time()
|
189
|
+
response = requests.request(
|
190
|
+
"PUT", presignedUrl, headers=headers, data=payload, timeout=timeout
|
191
|
+
)
|
192
|
+
elapsed_ms = (time.time() - start_time) * 1000
|
193
|
+
logger.debug(
|
194
|
+
f"API Call: [PUT] {presignedUrl} | Status: {response.status_code} | Time: {elapsed_ms:.2f}ms"
|
195
|
+
)
|
196
|
+
if response.status_code != 200 or response.status_code != 201:
|
197
|
+
return response, response.status_code
|
214
198
|
|
215
|
-
start_time = time.time()
|
216
|
-
response = session_manager.session.request(
|
217
|
-
"PUT", presignedUrl, headers=headers, data=payload, timeout=timeout
|
218
|
-
)
|
219
|
-
elapsed_ms = (time.time() - start_time) * 1000
|
220
|
-
logger.debug(
|
221
|
-
f"API Call: [PUT] {presignedUrl} | Status: {response.status_code} | Time: {elapsed_ms:.2f}ms"
|
222
|
-
)
|
223
|
-
if response.status_code not in [200, 201]:
|
224
|
-
return response, response.status_code
|
225
|
-
return True
|
226
|
-
except (PoolError, MaxRetryError, NewConnectionError, ConnectionError, Timeout) as e:
|
227
|
-
session_manager.handle_request_exceptions(e, "uploading zip to presigned URL")
|
228
|
-
return False
|
229
|
-
except RequestException as e:
|
230
|
-
logger.error(f"Failed to upload zip: {e}")
|
231
|
-
return False
|
232
199
|
|
233
200
|
def _insert_code(
|
234
201
|
dataset_name, hash_id, presigned_url, project_name, base_url=None, timeout=120
|
@@ -251,43 +218,39 @@ def _insert_code(
|
|
251
218
|
url_base = base_url if base_url is not None else RagaAICatalyst.BASE_URL
|
252
219
|
start_time = time.time()
|
253
220
|
endpoint = f"{url_base}/v2/llm/dataset/code"
|
254
|
-
response =
|
221
|
+
response = requests.request(
|
255
222
|
"POST", endpoint, headers=headers, data=payload, timeout=timeout
|
256
223
|
)
|
257
224
|
elapsed_ms = (time.time() - start_time) * 1000
|
258
225
|
logger.debug(
|
259
226
|
f"API Call: [POST] {endpoint} | Status: {response.status_code} | Time: {elapsed_ms:.2f}ms"
|
260
227
|
)
|
261
|
-
if response.status_code
|
228
|
+
if response.status_code == 200:
|
262
229
|
return response.json()["message"]
|
263
230
|
|
264
231
|
elif response.status_code == 401:
|
265
|
-
logger.warning("Received 401 error
|
232
|
+
logger.warning("Received 401 error. Attempting to refresh token.")
|
266
233
|
token = RagaAICatalyst.get_token(force_refresh=True)
|
267
234
|
headers = {
|
268
235
|
"X-Project-Name": project_name,
|
269
236
|
"Content-Type": "application/json",
|
270
237
|
"Authorization": f"Bearer {token}",
|
271
238
|
}
|
272
|
-
response =
|
239
|
+
response = requests.request(
|
273
240
|
"POST", endpoint, headers=headers, data=payload, timeout=timeout
|
274
241
|
)
|
275
242
|
elapsed_ms = (time.time() - start_time) * 1000
|
276
243
|
logger.debug(
|
277
244
|
f"API Call: [POST] {endpoint} | Status: {response.status_code} | Time: {elapsed_ms:.2f}ms"
|
278
245
|
)
|
279
|
-
if response.status_code
|
280
|
-
logger.info(f"Code inserted successfully after 401: {response.json()['message']}")
|
246
|
+
if response.status_code == 200:
|
281
247
|
return response.json()["message"]
|
282
248
|
else:
|
283
|
-
logger.error(f"Failed to insert code
|
284
|
-
|
249
|
+
logger.error(f"Failed to insert code: {response.json()['message']}")
|
250
|
+
pass
|
285
251
|
else:
|
286
252
|
logger.error(f"Failed to insert code: {response.json()['message']}")
|
287
|
-
|
288
|
-
except
|
289
|
-
session_manager.handle_request_exceptions(e, "inserting code")
|
290
|
-
return None
|
291
|
-
except RequestException as e:
|
253
|
+
pass
|
254
|
+
except requests.exceptions.RequestException as e:
|
292
255
|
logger.error(f"Failed to insert code: {e}")
|
293
|
-
|
256
|
+
pass
|
@@ -19,7 +19,7 @@ from ragaai_catalyst.tracers.agentic_tracing.utils.zip_list_of_unique_files impo
|
|
19
19
|
)
|
20
20
|
from ragaai_catalyst.tracers.utils.trace_json_converter import convert_json_format
|
21
21
|
|
22
|
-
logger = logging.getLogger(
|
22
|
+
logger = logging.getLogger(__name__)
|
23
23
|
logging_level = (
|
24
24
|
logger.setLevel(logging.DEBUG) if os.getenv("DEBUG") == "1" else logging.INFO
|
25
25
|
)
|
@@ -46,6 +46,7 @@ class RAGATraceExporter(SpanExporter):
|
|
46
46
|
self.external_id = external_id
|
47
47
|
|
48
48
|
def export(self, spans):
|
49
|
+
logger.debug("Starting export of span: ")
|
49
50
|
for span in spans:
|
50
51
|
try:
|
51
52
|
span_json = json.loads(span.to_json())
|
@@ -60,8 +61,11 @@ class RAGATraceExporter(SpanExporter):
|
|
60
61
|
|
61
62
|
if span_json["parent_id"] is None:
|
62
63
|
trace = self.trace_spans[trace_id]
|
64
|
+
logger.debug("End of trace found: ")
|
63
65
|
try:
|
66
|
+
logger.debug("Started processing complete trace: ")
|
64
67
|
self.process_complete_trace(trace, trace_id)
|
68
|
+
logger.debug("Completed processing complete trace: ")
|
65
69
|
except Exception as e:
|
66
70
|
logger.error(f"Error processing complete trace: {e}")
|
67
71
|
try:
|
@@ -84,9 +88,11 @@ class RAGATraceExporter(SpanExporter):
|
|
84
88
|
def process_complete_trace(self, spans, trace_id):
|
85
89
|
# Convert the trace to ragaai trace format
|
86
90
|
try:
|
91
|
+
logger.debug("Started preparing trace to trace format: ")
|
87
92
|
ragaai_trace_details = self.prepare_trace(spans, trace_id)
|
93
|
+
logger.debug("Completed preparing trace to trace format: ")
|
88
94
|
except Exception as e:
|
89
|
-
|
95
|
+
logger.error(f"Error preparing trace {trace_id}: {e}")
|
90
96
|
return # Exit early if conversion fails
|
91
97
|
|
92
98
|
# Check if trace details are None (conversion failed)
|
@@ -96,89 +102,109 @@ class RAGATraceExporter(SpanExporter):
|
|
96
102
|
|
97
103
|
# Upload the trace if upload_trace function is provided
|
98
104
|
try:
|
105
|
+
logger.debug("Started uploading trace: ")
|
99
106
|
if self.post_processor!=None:
|
100
107
|
ragaai_trace_details['trace_file_path'] = self.post_processor(ragaai_trace_details['trace_file_path'])
|
101
108
|
self.upload_trace(ragaai_trace_details, trace_id)
|
109
|
+
logger.debug("Completed uploading trace: ")
|
102
110
|
except Exception as e:
|
103
|
-
|
111
|
+
logger.error(f"Error uploading trace {trace_id}: {e}")
|
104
112
|
|
105
113
|
def prepare_trace(self, spans, trace_id):
|
106
114
|
try:
|
107
115
|
try:
|
116
|
+
logger.debug("Started converting trace to trace format: ")
|
108
117
|
ragaai_trace = convert_json_format(spans, self.custom_model_cost, self.user_context, self.user_gt,self.external_id)
|
118
|
+
logger.debug("Completed converting trace to trace format: ")
|
109
119
|
except Exception as e:
|
110
|
-
|
120
|
+
logger.error(f"Error in convert_json_format function: {trace_id}: {e}")
|
111
121
|
return None
|
112
122
|
|
113
123
|
try:
|
124
|
+
logger.debug("Started formatting interactions: ")
|
114
125
|
interactions = format_interactions(ragaai_trace)
|
115
126
|
ragaai_trace["workflow"] = interactions['workflow']
|
127
|
+
logger.debug("Completed formatting interactions: ")
|
116
128
|
except Exception as e:
|
117
|
-
|
129
|
+
logger.error(f"Error in format_interactions function: {trace_id}: {e}")
|
118
130
|
return None
|
119
131
|
|
120
132
|
try:
|
133
|
+
logger.debug("Started zipping source code: ")
|
121
134
|
# Add source code hash
|
122
135
|
hash_id, zip_path = zip_list_of_unique_files(
|
123
136
|
self.files_to_zip, output_dir=self.tmp_dir
|
124
137
|
)
|
138
|
+
logger.debug("Completed zipping source code: ")
|
125
139
|
except Exception as e:
|
126
|
-
|
140
|
+
logger.error(f"Error in zip_list_of_unique_files function: {trace_id}: {e}")
|
127
141
|
return None
|
128
142
|
|
129
143
|
try:
|
144
|
+
logger.debug("Started adding system info: ")
|
130
145
|
ragaai_trace["metadata"]["system_info"] = asdict(self.system_monitor.get_system_info())
|
131
146
|
ragaai_trace["metadata"]["resources"] = asdict(self.system_monitor.get_resources())
|
147
|
+
logger.debug("Completed adding system info: ")
|
132
148
|
except Exception as e:
|
133
|
-
|
149
|
+
logger.error(f"Error in get_system_info or get_resources function: {trace_id}: {e}")
|
134
150
|
return None
|
135
151
|
|
136
152
|
try:
|
153
|
+
logger.debug("Started adding source code hash: ")
|
137
154
|
ragaai_trace["metadata"]["system_info"]["source_code"] = hash_id
|
155
|
+
logger.debug("Completed adding source code hash: ")
|
138
156
|
except Exception as e:
|
139
|
-
|
157
|
+
logger.error(f"Error in adding source code hash: {trace_id}: {e}")
|
140
158
|
return None
|
141
159
|
|
142
160
|
try:
|
143
161
|
ragaai_trace["data"][0]["start_time"] = ragaai_trace["start_time"]
|
144
162
|
ragaai_trace["data"][0]["end_time"] = ragaai_trace["end_time"]
|
145
163
|
except Exception as e:
|
146
|
-
|
164
|
+
logger.error(f"Error in adding start_time or end_time: {trace_id}: {e}")
|
147
165
|
return None
|
148
166
|
|
149
167
|
try:
|
168
|
+
logger.debug("Started adding project name: ")
|
150
169
|
ragaai_trace["project_name"] = self.project_name
|
170
|
+
logger.debug("Completed adding project name: ")
|
151
171
|
except Exception as e:
|
152
|
-
|
172
|
+
logger.error(f"Error in adding project name: {trace_id}: {e}")
|
153
173
|
return None
|
154
174
|
|
155
175
|
try:
|
176
|
+
logger.debug("Started adding tracer type: ")
|
156
177
|
# Add tracer type to the trace
|
157
178
|
ragaai_trace["tracer_type"] = self.tracer_type
|
179
|
+
logger.debug("Completed adding tracer type: ")
|
158
180
|
except Exception as e:
|
159
|
-
|
181
|
+
logger.error(f"Error in adding tracer type: {trace_id}: {e}")
|
160
182
|
return None
|
161
183
|
|
162
184
|
#Add user passed metadata to the trace
|
163
185
|
try:
|
186
|
+
logger.debug("Started adding user passed metadata: ")
|
164
187
|
if self.user_details.get("trace_user_detail").get("metadata") and isinstance(self.user_details.get("trace_user_detail").get("metadata"), dict):
|
165
188
|
for key, value in self.user_details.get("trace_user_detail").get("metadata").items():
|
166
189
|
if key in ["log_source", "recorded_on"]:
|
167
190
|
continue
|
168
191
|
ragaai_trace["metadata"][key] = value
|
192
|
+
logger.debug("Completed adding user passed metadata: ")
|
169
193
|
except Exception as e:
|
170
|
-
|
194
|
+
logger.error(f"Error in adding metadata: {trace_id}: {e}")
|
171
195
|
return None
|
172
196
|
|
173
197
|
try:
|
198
|
+
logger.debug("Started saving trace json: ")
|
174
199
|
# Save the trace_json
|
175
200
|
trace_file_path = os.path.join(self.tmp_dir, f"{trace_id}.json")
|
176
201
|
with open(trace_file_path, "w") as file:
|
177
202
|
json.dump(ragaai_trace, file, cls=TracerJSONEncoder, indent=2)
|
178
203
|
with open(os.path.join(os.getcwd(), 'rag_agent_traces.json'), 'w') as f:
|
179
204
|
json.dump(ragaai_trace, f, cls=TracerJSONEncoder, indent=2)
|
205
|
+
logger.debug("Completed saving trace json: ")
|
180
206
|
except Exception as e:
|
181
|
-
|
207
|
+
logger.error(f"Error in saving trace json: {trace_id}: {e}")
|
182
208
|
return None
|
183
209
|
|
184
210
|
return {
|
@@ -187,7 +213,7 @@ class RAGATraceExporter(SpanExporter):
|
|
187
213
|
'hash_id': hash_id
|
188
214
|
}
|
189
215
|
except Exception as e:
|
190
|
-
|
216
|
+
logger.error(f"Error converting trace {trace_id}: {str(e)}")
|
191
217
|
return None
|
192
218
|
|
193
219
|
def upload_trace(self, ragaai_trace_details, trace_id):
|
@@ -203,7 +229,6 @@ class RAGATraceExporter(SpanExporter):
|
|
203
229
|
dataset_name=self.dataset_name,
|
204
230
|
user_details=self.user_details,
|
205
231
|
base_url=self.base_url,
|
206
|
-
tracer_type=self.tracer_type,
|
207
232
|
timeout=self.timeout
|
208
233
|
)
|
209
234
|
|
@@ -127,9 +127,11 @@ class Tracer(AgenticTracing):
|
|
127
127
|
self.model_custom_cost = {}
|
128
128
|
super().__init__(user_detail=user_detail, auto_instrumentation=auto_instrumentation)
|
129
129
|
|
130
|
+
logger.debug(f"Setting up Tracer instance with project: {project_name}, dataset: {dataset_name}")
|
130
131
|
self.project_name = project_name
|
131
132
|
self.dataset_name = dataset_name
|
132
133
|
self.tracer_type = tracer_type
|
134
|
+
logger.debug(f"Tracer type set to: {tracer_type}")
|
133
135
|
self.metadata = self._improve_metadata(metadata, tracer_type)
|
134
136
|
# self.metadata["total_cost"] = 0.0
|
135
137
|
# self.metadata["total_tokens"] = 0
|
@@ -146,12 +148,16 @@ class Tracer(AgenticTracing):
|
|
146
148
|
self.file_tracker = TrackName()
|
147
149
|
self.post_processor = None
|
148
150
|
self.max_upload_workers = max_upload_workers
|
151
|
+
logger.debug(f"Max upload workers: {self.max_upload_workers}")
|
149
152
|
self.user_details = self._pass_user_data()
|
150
153
|
self.update_llm_cost = update_llm_cost
|
151
154
|
self.auto_instrumentation = auto_instrumentation
|
152
155
|
self.external_id = external_id
|
156
|
+
if external_id:
|
157
|
+
logger.debug(f"External ID provided: {external_id}")
|
153
158
|
|
154
159
|
try:
|
160
|
+
logger.debug(f"Fetching projects list from {self.base_url}/v2/llm/projects")
|
155
161
|
response = requests.get(
|
156
162
|
f"{self.base_url}/v2/llm/projects?size={self.num_projects}",
|
157
163
|
headers={
|
@@ -165,8 +171,13 @@ class Tracer(AgenticTracing):
|
|
165
171
|
project_list = [
|
166
172
|
project["name"] for project in response.json()["data"]["content"]
|
167
173
|
]
|
174
|
+
logger.debug(f"Found {len(project_list)} projects")
|
168
175
|
if project_name not in project_list:
|
169
|
-
logger.
|
176
|
+
logger.warning(f"Project '{project_name}' not found in available projects")
|
177
|
+
logger.debug(f"Available projects: {project_list}")
|
178
|
+
else:
|
179
|
+
logger.debug(f"Project '{project_name}' found in available projects")
|
180
|
+
|
170
181
|
|
171
182
|
self.project_id = [
|
172
183
|
project["id"] for project in response.json()["data"]["content"] if project["name"] == project_name
|
@@ -177,6 +188,7 @@ class Tracer(AgenticTracing):
|
|
177
188
|
|
178
189
|
except requests.exceptions.RequestException as e:
|
179
190
|
logger.error(f"Failed to retrieve projects list: {e}")
|
191
|
+
logger.debug(f"Request exception details: {str(e)}, URL: {self.base_url}/v2/llm/projects")
|
180
192
|
|
181
193
|
# if tracer_type == "langchain":
|
182
194
|
# instrumentors = []
|
@@ -191,13 +203,16 @@ class Tracer(AgenticTracing):
|
|
191
203
|
# from openinference.instrumentation.langchain import LangChainInstrumentor
|
192
204
|
# instrumentors += [(LangChainInstrumentor, [])]
|
193
205
|
# self._setup_agentic_tracer(instrumentors)
|
206
|
+
|
194
207
|
# Handle agentic tracers
|
208
|
+
logger.debug(f"Starting Instrumentation for tracer type: {tracer_type}")
|
195
209
|
if tracer_type == "agentic" or tracer_type.startswith("agentic/") or tracer_type == "langchain":
|
196
210
|
# Setup instrumentors based on tracer type
|
197
211
|
instrumentors = []
|
198
212
|
|
199
213
|
# Add LLM Instrumentors
|
200
214
|
if tracer_type in ['agentic/crewai']:
|
215
|
+
logger.debug("Setting up instrumentors for CrewAI")
|
201
216
|
try:
|
202
217
|
from openinference.instrumentation.vertexai import VertexAIInstrumentor
|
203
218
|
instrumentors.append((VertexAIInstrumentor, []))
|
@@ -310,31 +325,38 @@ class Tracer(AgenticTracing):
|
|
310
325
|
elif tracer_type == "agentic/llamaindex" or tracer_type == "llamaindex":
|
311
326
|
from openinference.instrumentation.llama_index import LlamaIndexInstrumentor
|
312
327
|
instrumentors += [(LlamaIndexInstrumentor, [])]
|
328
|
+
logger.info("Instrumenting LlamaIndex...")
|
313
329
|
|
314
330
|
elif tracer_type == "agentic/langchain" or tracer_type == "agentic/langgraph" or tracer_type == "langchain":
|
315
331
|
from openinference.instrumentation.langchain import LangChainInstrumentor
|
316
332
|
instrumentors += [(LangChainInstrumentor, [])]
|
333
|
+
logger.info("Instrumenting LangChain...")
|
317
334
|
|
318
335
|
elif tracer_type == "agentic/crewai":
|
319
336
|
from openinference.instrumentation.crewai import CrewAIInstrumentor
|
320
337
|
from openinference.instrumentation.langchain import LangChainInstrumentor
|
321
338
|
instrumentors += [(CrewAIInstrumentor, []), (LangChainInstrumentor, [])]
|
339
|
+
logger.info("Instrumenting CrewAI...")
|
322
340
|
|
323
341
|
elif tracer_type == "agentic/haystack":
|
324
342
|
from openinference.instrumentation.haystack import HaystackInstrumentor
|
325
343
|
instrumentors += [(HaystackInstrumentor, [])]
|
344
|
+
logger.info("Instrumenting Haystack...")
|
326
345
|
|
327
346
|
elif tracer_type == "agentic/autogen":
|
328
347
|
from openinference.instrumentation.autogen import AutogenInstrumentor
|
329
348
|
instrumentors += [(AutogenInstrumentor, [])]
|
349
|
+
logger.info("Instrumenting Autogen...")
|
330
350
|
|
331
351
|
elif tracer_type == "agentic/smolagents":
|
332
352
|
from openinference.instrumentation.smolagents import SmolagentsInstrumentor
|
333
353
|
instrumentors += [(SmolagentsInstrumentor, [])]
|
354
|
+
logger.info("Instrumenting Smolagents...")
|
334
355
|
|
335
356
|
elif tracer_type == "agentic/openai_agents":
|
336
357
|
from openinference.instrumentation.openai_agents import OpenAIAgentsInstrumentor
|
337
358
|
instrumentors += [(OpenAIAgentsInstrumentor, [])]
|
359
|
+
logger.info("Instrumenting OpenAI Agents...")
|
338
360
|
|
339
361
|
else:
|
340
362
|
# Unknown agentic tracer type
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: ragaai_catalyst
|
3
|
-
Version: 2.2.4.
|
3
|
+
Version: 2.2.4.1b3
|
4
4
|
Summary: RAGA AI CATALYST
|
5
5
|
Author-email: Kiran Scaria <kiran.scaria@raga.ai>, Kedar Gaikwad <kedar.gaikwad@raga.ai>, Dushyant Mahajan <dushyant.mahajan@raga.ai>, Siddhartha Kosti <siddhartha.kosti@raga.ai>, Ritika Goel <ritika.goel@raga.ai>, Vijay Chaurasia <vijay.chaurasia@raga.ai>, Tushar Kumar <tushar.kumar@raga.ai>, Rishabh Pandey <rishabh.pandey@raga.ai>, Jyotsana C G <jyotsana@raga.ai>
|
6
6
|
Requires-Python: <=3.13.2,>=3.10
|
@@ -31,7 +31,7 @@ ragaai_catalyst/tracers/distributed.py,sha256=CGPuOh4CsgEk428PPibieLaAG2Tt3BVygF
|
|
31
31
|
ragaai_catalyst/tracers/langchain_callback.py,sha256=CB75zzG3-DkYTELj0vI1MOHQTY0MuQJfoHIXz9Cl8S8,34568
|
32
32
|
ragaai_catalyst/tracers/llamaindex_callback.py,sha256=ZY0BJrrlz-P9Mg2dX-ZkVKG3gSvzwqBtk7JL_05MiYA,14028
|
33
33
|
ragaai_catalyst/tracers/llamaindex_instrumentation.py,sha256=Ys_jLkvVqo12bKgXDmkp4TxJu9HkBATrFE8cIcTYxWw,14329
|
34
|
-
ragaai_catalyst/tracers/tracer.py,sha256=
|
34
|
+
ragaai_catalyst/tracers/tracer.py,sha256=2JmeM9OkxNyS6XG0Ogqhx8q9lvy3vNLJnEVH2Vg2RNM,42768
|
35
35
|
ragaai_catalyst/tracers/upload_traces.py,sha256=w1clGGfdOMpStUJX40NAlxe6dcFdN4pwcezyII0bGYA,6994
|
36
36
|
ragaai_catalyst/tracers/agentic_tracing/README.md,sha256=X4QwLb7-Jg7GQMIXj-SerZIgDETfw-7VgYlczOR8ZeQ,4508
|
37
37
|
ragaai_catalyst/tracers/agentic_tracing/__init__.py,sha256=yf6SKvOPSpH-9LiKaoLKXwqj5sez8F_5wkOb91yp0oE,260
|
@@ -54,10 +54,9 @@ ragaai_catalyst/tracers/agentic_tracing/tracers/network_tracer.py,sha256=m8CxYkl
|
|
54
54
|
ragaai_catalyst/tracers/agentic_tracing/tracers/tool_tracer.py,sha256=xxrliKPfdfbIZRZqMnUewsaTD8_Hv0dbuoBivNZGD4U,21674
|
55
55
|
ragaai_catalyst/tracers/agentic_tracing/tracers/user_interaction_tracer.py,sha256=bhSUhNQCuJXKjgJAXhjKEYjnHMpYN90FSZdR84fNIKU,4614
|
56
56
|
ragaai_catalyst/tracers/agentic_tracing/upload/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
57
|
-
ragaai_catalyst/tracers/agentic_tracing/upload/
|
58
|
-
ragaai_catalyst/tracers/agentic_tracing/upload/
|
59
|
-
ragaai_catalyst/tracers/agentic_tracing/upload/
|
60
|
-
ragaai_catalyst/tracers/agentic_tracing/upload/upload_code.py,sha256=hJv-LST4rGbldG9k075otjfHZRRurQKyUHClD5HXs4s,12015
|
57
|
+
ragaai_catalyst/tracers/agentic_tracing/upload/trace_uploader.py,sha256=iMUMFR9XVipCBunpv8_No8bCoP3lqG47M5dg-ugibWo,21006
|
58
|
+
ragaai_catalyst/tracers/agentic_tracing/upload/upload_agentic_traces.py,sha256=KOtnB-QFpVFD0zKpJ2epOq8r0tSdFPRKe0rTA53A5Zo,12738
|
59
|
+
ragaai_catalyst/tracers/agentic_tracing/upload/upload_code.py,sha256=2mxdi7k_SoDqQUFo1oQ__28CpmSIvVugYcbuRltUK9Q,9920
|
61
60
|
ragaai_catalyst/tracers/agentic_tracing/upload/upload_local_metric.py,sha256=m1O8lKpxKwtHofXLW3fTHX5yfqDW5GxoveARlg5cTw4,2571
|
62
61
|
ragaai_catalyst/tracers/agentic_tracing/utils/__init__.py,sha256=XdB3X_ufe4RVvGorxSqAiB9dYv4UD7Hvvuw3bsDUppY,60
|
63
62
|
ragaai_catalyst/tracers/agentic_tracing/utils/api_utils.py,sha256=ZduFA7MmTnWfQ2FzSD0hxMAAfNNTgBs4CXcHZdXJv6k,749
|
@@ -77,7 +76,7 @@ ragaai_catalyst/tracers/exporters/__init__.py,sha256=wQbaqyeIjVZxYprHCKZ9BeiqxeX
|
|
77
76
|
ragaai_catalyst/tracers/exporters/dynamic_trace_exporter.py,sha256=Rm-QaLv1qMAKpHKcFOcK_HWaKHwFBoUH45_4QYipE-g,6843
|
78
77
|
ragaai_catalyst/tracers/exporters/file_span_exporter.py,sha256=NZsD3rShUiC3rO9y3Y2vqEtS3MO51FXZy0p3q9cdDNY,6403
|
79
78
|
ragaai_catalyst/tracers/exporters/raga_exporter.py,sha256=l-RfysTIXYxtvYkVlJbRvg-AzJbT4Fdb-YiZh0mfuDs,17868
|
80
|
-
ragaai_catalyst/tracers/exporters/ragaai_trace_exporter.py,sha256=
|
79
|
+
ragaai_catalyst/tracers/exporters/ragaai_trace_exporter.py,sha256=H6nQBjUTyraPxSPj8y71sslng3yz_y-LbbmbX3FDmRM,10758
|
81
80
|
ragaai_catalyst/tracers/instrumentators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
82
81
|
ragaai_catalyst/tracers/utils/__init__.py,sha256=KeMaZtYaTojilpLv65qH08QmpYclfpacDA0U3wg6Ybw,64
|
83
82
|
ragaai_catalyst/tracers/utils/convert_langchain_callbacks_output.py,sha256=SehrD7q8ytAiUYoWr406b4mWs3Lk0Rcy6Ekkihh22TI,1703
|
@@ -89,8 +88,8 @@ ragaai_catalyst/tracers/utils/rag_extraction_logic_final.py,sha256=3ygkRT__lLDRf
|
|
89
88
|
ragaai_catalyst/tracers/utils/rag_trace_json_converter.py,sha256=54IEZO-YRjUAahV5nw8KClXqTF1LhfDry_TsZ4KGow4,20467
|
90
89
|
ragaai_catalyst/tracers/utils/trace_json_converter.py,sha256=-HZVmijeUFLO7e9OAvi1RJdWVTxPRUHPd1MkKQlCD54,11785
|
91
90
|
ragaai_catalyst/tracers/utils/utils.py,sha256=o-p9n2ZuophdrV0wrixu-BqRHCkovup_klc3mS8mU8g,2374
|
92
|
-
ragaai_catalyst-2.2.4.
|
93
|
-
ragaai_catalyst-2.2.4.
|
94
|
-
ragaai_catalyst-2.2.4.
|
95
|
-
ragaai_catalyst-2.2.4.
|
96
|
-
ragaai_catalyst-2.2.4.
|
91
|
+
ragaai_catalyst-2.2.4.1b3.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
92
|
+
ragaai_catalyst-2.2.4.1b3.dist-info/METADATA,sha256=Z9KlRyR8KC6lT1tp6WDqxpj19AegssW2_uGZPnaG2es,17681
|
93
|
+
ragaai_catalyst-2.2.4.1b3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
94
|
+
ragaai_catalyst-2.2.4.1b3.dist-info/top_level.txt,sha256=HpgsdRgEJMk8nqrU6qdCYk3di7MJkDL0B19lkc7dLfM,16
|
95
|
+
ragaai_catalyst-2.2.4.1b3.dist-info/RECORD,,
|
@@ -1,92 +0,0 @@
|
|
1
|
-
import logging
|
2
|
-
import threading
|
3
|
-
|
4
|
-
from requests.adapters import HTTPAdapter
|
5
|
-
from urllib3.util.retry import Retry
|
6
|
-
from urllib3.exceptions import PoolError, MaxRetryError, NewConnectionError
|
7
|
-
from requests.exceptions import ConnectionError, Timeout, RequestException
|
8
|
-
import requests
|
9
|
-
|
10
|
-
logger = logging.getLogger(__name__)
|
11
|
-
|
12
|
-
|
13
|
-
class SessionManager:
|
14
|
-
"""Shared session manager with connection pooling for HTTP requests"""
|
15
|
-
_instance = None
|
16
|
-
_session = None
|
17
|
-
_lock = threading.Lock()
|
18
|
-
|
19
|
-
def __new__(cls):
|
20
|
-
if cls._instance is None:
|
21
|
-
with cls._lock: # Thread-safe singleton
|
22
|
-
if cls._instance is None: # Double-check locking
|
23
|
-
logger.info("Creating new SessionManager singleton instance")
|
24
|
-
cls._instance = super(SessionManager, cls).__new__(cls)
|
25
|
-
cls._instance._initialize_session()
|
26
|
-
else:
|
27
|
-
logger.debug("SessionManager instance already exists, returning existing instance")
|
28
|
-
else:
|
29
|
-
logger.debug("SessionManager instance exists, returning existing instance")
|
30
|
-
return cls._instance
|
31
|
-
|
32
|
-
def _initialize_session(self):
|
33
|
-
"""Initialize session with connection pooling and retry strategy"""
|
34
|
-
logger.info("Initializing HTTP session with connection pooling and retry strategy")
|
35
|
-
self._session = requests.Session()
|
36
|
-
|
37
|
-
retry_strategy = Retry(
|
38
|
-
total=3, # number of retries
|
39
|
-
backoff_factor=0.5, # wait 0.5, 1, 2... seconds between retries
|
40
|
-
status_forcelist=[500, 502, 503, 504] # HTTP status codes to retry on
|
41
|
-
)
|
42
|
-
|
43
|
-
adapter = HTTPAdapter(
|
44
|
-
max_retries=retry_strategy,
|
45
|
-
pool_connections=2, # number of connections to keep in the pool
|
46
|
-
pool_maxsize=50, # maximum number of connections in the pool
|
47
|
-
pool_block=True
|
48
|
-
)
|
49
|
-
logger.debug(f"Configured HTTP adapter: pool_connections={adapter.config.get('pool_connections', 1)}, "
|
50
|
-
f"pool_maxsize={adapter.config.get('pool_maxsize', 50)}, "
|
51
|
-
f"pool_block={adapter.config.get('pool_block', False)}")
|
52
|
-
|
53
|
-
self._session.mount("http://", adapter)
|
54
|
-
self._session.mount("https://", adapter)
|
55
|
-
logger.info("HTTP session initialized successfully with adapters mounted for http:// and https://")
|
56
|
-
|
57
|
-
@property
|
58
|
-
def session(self):
|
59
|
-
if self._session is None:
|
60
|
-
logger.warning("Session accessed but not initialized, reinitializing...")
|
61
|
-
self._initialize_session()
|
62
|
-
return self._session
|
63
|
-
|
64
|
-
def close(self):
|
65
|
-
"""Close the session"""
|
66
|
-
if self._session:
|
67
|
-
logger.info("Closing HTTP session")
|
68
|
-
self._session.close()
|
69
|
-
self._session = None
|
70
|
-
logger.info("HTTP session closed successfully")
|
71
|
-
else:
|
72
|
-
logger.debug("Close called but session was already None")
|
73
|
-
|
74
|
-
def handle_request_exceptions(self, e, operation_name):
|
75
|
-
"""Handle common request exceptions with appropriate logging"""
|
76
|
-
logger.error(f"Exception occurred during {operation_name}")
|
77
|
-
if isinstance(e, (PoolError, MaxRetryError)):
|
78
|
-
logger.error(f"Connection pool exhausted during {operation_name}: {e}")
|
79
|
-
elif isinstance(e, NewConnectionError):
|
80
|
-
logger.error(f"Failed to establish new connection during {operation_name}: {e}")
|
81
|
-
elif isinstance(e, ConnectionError):
|
82
|
-
logger.error(f"Connection error during {operation_name}: {e}")
|
83
|
-
elif isinstance(e, Timeout):
|
84
|
-
logger.error(f"Request timeout during {operation_name}: {e}")
|
85
|
-
else:
|
86
|
-
logger.error(f"Unexpected error during {operation_name}: {e}")
|
87
|
-
|
88
|
-
|
89
|
-
# Global session manager instance
|
90
|
-
logger.info("Creating global SessionManager instance")
|
91
|
-
session_manager = SessionManager()
|
92
|
-
logger.info(f"Global SessionManager instance created with ID: {id(session_manager)}")
|
File without changes
|
{ragaai_catalyst-2.2.4.1b1.dist-info → ragaai_catalyst-2.2.4.1b3.dist-info}/licenses/LICENSE
RENAMED
File without changes
|
File without changes
|