agentreplay 0.1.2__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.
- agentreplay/__init__.py +81 -0
- agentreplay/auto_instrument/__init__.py +237 -0
- agentreplay/auto_instrument/openai.py +431 -0
- agentreplay/batching.py +270 -0
- agentreplay/bootstrap.py +202 -0
- agentreplay/circuit_breaker.py +300 -0
- agentreplay/client.py +1560 -0
- agentreplay/config.py +215 -0
- agentreplay/context.py +168 -0
- agentreplay/env_config.py +327 -0
- agentreplay/env_init.py +128 -0
- agentreplay/exceptions.py +92 -0
- agentreplay/genai.py +510 -0
- agentreplay/genai_conventions.py +502 -0
- agentreplay/install_pth.py +159 -0
- agentreplay/langchain_tracer.py +385 -0
- agentreplay/models.py +120 -0
- agentreplay/otel_bridge.py +281 -0
- agentreplay/patch.py +308 -0
- agentreplay/propagation.py +328 -0
- agentreplay/py.typed +3 -0
- agentreplay/retry.py +151 -0
- agentreplay/sampling.py +298 -0
- agentreplay/session.py +164 -0
- agentreplay/sitecustomize.py +73 -0
- agentreplay/span.py +270 -0
- agentreplay/unified.py +465 -0
- agentreplay-0.1.2.dist-info/METADATA +285 -0
- agentreplay-0.1.2.dist-info/RECORD +33 -0
- agentreplay-0.1.2.dist-info/WHEEL +5 -0
- agentreplay-0.1.2.dist-info/entry_points.txt +2 -0
- agentreplay-0.1.2.dist-info/licenses/LICENSE +190 -0
- agentreplay-0.1.2.dist-info/top_level.txt +1 -0
agentreplay/__init__.py
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# Copyright 2025 Sushanth (https://github.com/sushanthpy)
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
"""Agentreplay Python SDK - Agent Trace Engine for LLM Agents."""
|
|
16
|
+
|
|
17
|
+
from agentreplay.client import AgentreplayClient
|
|
18
|
+
from agentreplay.models import SpanType, AgentFlowEdge
|
|
19
|
+
from agentreplay.span import Span
|
|
20
|
+
from agentreplay.config import AgentreplayConfig, get_config, set_config, reset_config
|
|
21
|
+
from agentreplay.batching import BatchingAgentreplayClient
|
|
22
|
+
from agentreplay.session import Session
|
|
23
|
+
from agentreplay.retry import retry_with_backoff
|
|
24
|
+
from agentreplay.exceptions import (
|
|
25
|
+
AgentreplayError,
|
|
26
|
+
AuthenticationError,
|
|
27
|
+
RateLimitError,
|
|
28
|
+
ServerError,
|
|
29
|
+
ValidationError,
|
|
30
|
+
NotFoundError,
|
|
31
|
+
NetworkError,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
# Agent Context Tracking
|
|
35
|
+
from agentreplay.context import AgentContext
|
|
36
|
+
|
|
37
|
+
# Auto-instrumentation (Pure OpenTelemetry)
|
|
38
|
+
from agentreplay.auto_instrument import auto_instrument, setup_instrumentation
|
|
39
|
+
|
|
40
|
+
# OTEL Bridge & Bootstrap
|
|
41
|
+
from agentreplay.bootstrap import init_otel_instrumentation, is_initialized
|
|
42
|
+
from agentreplay.otel_bridge import get_tracer
|
|
43
|
+
|
|
44
|
+
__version__ = "0.1.2"
|
|
45
|
+
|
|
46
|
+
__all__ = [
|
|
47
|
+
# Core client
|
|
48
|
+
"AgentreplayClient",
|
|
49
|
+
"BatchingAgentreplayClient",
|
|
50
|
+
# Models
|
|
51
|
+
"SpanType",
|
|
52
|
+
"AgentFlowEdge",
|
|
53
|
+
"Span",
|
|
54
|
+
# Configuration
|
|
55
|
+
"AgentreplayConfig",
|
|
56
|
+
"get_config",
|
|
57
|
+
"set_config",
|
|
58
|
+
"reset_config",
|
|
59
|
+
# Session management
|
|
60
|
+
"Session",
|
|
61
|
+
# Retry utilities
|
|
62
|
+
"retry_with_backoff",
|
|
63
|
+
# Agent Context
|
|
64
|
+
"AgentContext",
|
|
65
|
+
# Auto-instrumentation (Pure OpenTelemetry)
|
|
66
|
+
"auto_instrument",
|
|
67
|
+
"setup_instrumentation",
|
|
68
|
+
# OTEL Initialization
|
|
69
|
+
"init_otel_instrumentation",
|
|
70
|
+
"is_initialized",
|
|
71
|
+
# OTEL Bridge
|
|
72
|
+
"get_tracer",
|
|
73
|
+
# Exceptions
|
|
74
|
+
"AgentreplayError",
|
|
75
|
+
"AuthenticationError",
|
|
76
|
+
"RateLimitError",
|
|
77
|
+
"ServerError",
|
|
78
|
+
"ValidationError",
|
|
79
|
+
"NotFoundError",
|
|
80
|
+
"NetworkError",
|
|
81
|
+
]
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
# Copyright 2025 Sushanth (https://github.com/sushanthpy)
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
"""Automatic instrumentation using OpenTelemetry.
|
|
16
|
+
|
|
17
|
+
This module provides zero-code observability by leveraging the official
|
|
18
|
+
OpenTelemetry instrumentation ecosystem. We don't maintain framework-specific
|
|
19
|
+
integrations - we use the community-maintained OTEL instrumentations.
|
|
20
|
+
|
|
21
|
+
Example:
|
|
22
|
+
>>> from agentreplay import auto_instrument
|
|
23
|
+
>>> auto_instrument("my-service")
|
|
24
|
+
>>>
|
|
25
|
+
>>> # Now all instrumented libraries automatically emit spans!
|
|
26
|
+
>>> from openai import OpenAI
|
|
27
|
+
>>> client = OpenAI()
|
|
28
|
+
>>> response = client.chat.completions.create(...) # ✓ Traced via OTEL
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
from typing import Optional
|
|
32
|
+
import logging
|
|
33
|
+
import os
|
|
34
|
+
|
|
35
|
+
logger = logging.getLogger(__name__)
|
|
36
|
+
|
|
37
|
+
_instrumented = False
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def auto_instrument(
|
|
41
|
+
service_name: str,
|
|
42
|
+
otlp_endpoint: str = "localhost:47117",
|
|
43
|
+
tenant_id: int = 1,
|
|
44
|
+
project_id: int = 0,
|
|
45
|
+
capture_content: bool = True,
|
|
46
|
+
debug: bool = False,
|
|
47
|
+
) -> None:
|
|
48
|
+
"""Automatically instrument using OpenTelemetry.
|
|
49
|
+
|
|
50
|
+
Sets up OTLP exporter and automatically instruments all available
|
|
51
|
+
libraries using their official OTEL instrumentations.
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
service_name: Name of your service
|
|
55
|
+
otlp_endpoint: OTLP gRPC endpoint (default: localhost:47117)
|
|
56
|
+
tenant_id: Tenant ID (added to resource attributes)
|
|
57
|
+
project_id: Project ID (added to resource attributes)
|
|
58
|
+
capture_content: Capture LLM request/response content (default: True)
|
|
59
|
+
debug: Enable debug logging (default: False)
|
|
60
|
+
"""
|
|
61
|
+
global _instrumented
|
|
62
|
+
|
|
63
|
+
if _instrumented:
|
|
64
|
+
logger.warning("Already instrumented. Skipping.")
|
|
65
|
+
return
|
|
66
|
+
|
|
67
|
+
if debug:
|
|
68
|
+
logging.basicConfig(level=logging.DEBUG)
|
|
69
|
+
logger.setLevel(logging.DEBUG)
|
|
70
|
+
|
|
71
|
+
logger.info(f"🚀 Setting up Agentreplay OpenTelemetry for service: {service_name}")
|
|
72
|
+
|
|
73
|
+
try:
|
|
74
|
+
# Use the otel_bridge to set up tracer provider
|
|
75
|
+
from agentreplay.otel_bridge import setup_tracer_provider
|
|
76
|
+
|
|
77
|
+
setup_tracer_provider(
|
|
78
|
+
service_name=service_name,
|
|
79
|
+
otlp_endpoint=otlp_endpoint,
|
|
80
|
+
tenant_id=tenant_id,
|
|
81
|
+
project_id=project_id,
|
|
82
|
+
debug=debug,
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
logger.info(f"✓ OTLP exporter configured: {otlp_endpoint}")
|
|
86
|
+
|
|
87
|
+
# Set environment for OpenAI instrumentation
|
|
88
|
+
if capture_content:
|
|
89
|
+
os.environ["AGENTREPLAY_CAPTURE_CONTENT"] = "true"
|
|
90
|
+
else:
|
|
91
|
+
os.environ["AGENTREPLAY_CAPTURE_CONTENT"] = "false"
|
|
92
|
+
|
|
93
|
+
# Auto-discover and instrument everything
|
|
94
|
+
_auto_instrument_all()
|
|
95
|
+
|
|
96
|
+
_instrumented = True
|
|
97
|
+
logger.info("✅ Auto-instrumentation complete")
|
|
98
|
+
|
|
99
|
+
except Exception as e:
|
|
100
|
+
logger.error(f"❌ Failed to setup OpenTelemetry: {e}")
|
|
101
|
+
raise
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def _auto_instrument_all():
|
|
105
|
+
"""Auto-instrument all available libraries using official OTEL instrumentations."""
|
|
106
|
+
|
|
107
|
+
instrumented = []
|
|
108
|
+
|
|
109
|
+
# Enable content capture for GenAI instrumentations (OTEL standard)
|
|
110
|
+
import os
|
|
111
|
+
capture_content = os.getenv("AGENTREPLAY_CAPTURE_CONTENT", "true").lower() in {"1", "true", "yes"}
|
|
112
|
+
if capture_content:
|
|
113
|
+
os.environ["OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT"] = "true"
|
|
114
|
+
|
|
115
|
+
# Try OpenAI
|
|
116
|
+
try:
|
|
117
|
+
from opentelemetry.instrumentation.openai import OpenAIInstrumentor
|
|
118
|
+
OpenAIInstrumentor().instrument()
|
|
119
|
+
instrumented.append("OpenAI")
|
|
120
|
+
except ImportError:
|
|
121
|
+
pass
|
|
122
|
+
except Exception as e:
|
|
123
|
+
logger.debug(f"OpenAI instrumentation failed: {e}")
|
|
124
|
+
|
|
125
|
+
# Try Anthropic
|
|
126
|
+
try:
|
|
127
|
+
from opentelemetry.instrumentation.anthropic import AnthropicInstrumentor
|
|
128
|
+
AnthropicInstrumentor().instrument()
|
|
129
|
+
instrumented.append("Anthropic")
|
|
130
|
+
except ImportError:
|
|
131
|
+
pass
|
|
132
|
+
except Exception as e:
|
|
133
|
+
logger.debug(f"Anthropic instrumentation failed: {e}")
|
|
134
|
+
|
|
135
|
+
# Try LangChain - use custom Agentreplay callback handler for hierarchy
|
|
136
|
+
try:
|
|
137
|
+
from agentreplay.langchain_tracer import get_agentreplay_callback
|
|
138
|
+
|
|
139
|
+
callback = get_agentreplay_callback()
|
|
140
|
+
if callback:
|
|
141
|
+
# Register globally for all LangChain operations
|
|
142
|
+
import langchain_core.callbacks.manager as manager
|
|
143
|
+
if hasattr(manager, '_default_callback_handlers'):
|
|
144
|
+
if not hasattr(manager._default_callback_handlers, '__iter__'):
|
|
145
|
+
manager._default_callback_handlers = []
|
|
146
|
+
manager._default_callback_handlers.append(callback)
|
|
147
|
+
instrumented.append("LangChain")
|
|
148
|
+
except ImportError:
|
|
149
|
+
pass # LangChain not installed
|
|
150
|
+
except Exception as e:
|
|
151
|
+
logger.debug(f"LangChain instrumentation failed: {e}")
|
|
152
|
+
|
|
153
|
+
# Try LlamaIndex
|
|
154
|
+
try:
|
|
155
|
+
from opentelemetry.instrumentation.llamaindex import LlamaIndexInstrumentor
|
|
156
|
+
LlamaIndexInstrumentor().instrument()
|
|
157
|
+
instrumented.append("LlamaIndex")
|
|
158
|
+
except ImportError:
|
|
159
|
+
pass
|
|
160
|
+
except Exception as e:
|
|
161
|
+
logger.debug(f"LlamaIndex instrumentation failed: {e}")
|
|
162
|
+
|
|
163
|
+
# Try HTTP clients (requests, httpx, urllib3)
|
|
164
|
+
try:
|
|
165
|
+
from opentelemetry.instrumentation.requests import RequestsInstrumentor
|
|
166
|
+
RequestsInstrumentor().instrument()
|
|
167
|
+
instrumented.append("requests")
|
|
168
|
+
except ImportError:
|
|
169
|
+
pass
|
|
170
|
+
except Exception as e:
|
|
171
|
+
logger.debug(f"requests instrumentation failed: {e}")
|
|
172
|
+
|
|
173
|
+
try:
|
|
174
|
+
from opentelemetry.instrumentation.httpx import HTTPXClientInstrumentor
|
|
175
|
+
HTTPXClientInstrumentor().instrument()
|
|
176
|
+
instrumented.append("httpx")
|
|
177
|
+
except ImportError:
|
|
178
|
+
pass
|
|
179
|
+
except Exception as e:
|
|
180
|
+
logger.debug(f"httpx instrumentation failed: {e}")
|
|
181
|
+
|
|
182
|
+
if instrumented:
|
|
183
|
+
logger.info(f"✓ Instrumented: {', '.join(instrumented)}")
|
|
184
|
+
else:
|
|
185
|
+
logger.warning("No instrumentable libraries found. Install opentelemetry-instrumentation-* packages.")
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def setup_instrumentation(
|
|
189
|
+
service_name: Optional[str] = None,
|
|
190
|
+
otlp_endpoint: Optional[str] = None,
|
|
191
|
+
tenant_id: Optional[int] = None,
|
|
192
|
+
project_id: Optional[int] = None,
|
|
193
|
+
capture_content: Optional[bool] = None,
|
|
194
|
+
debug: Optional[bool] = None,
|
|
195
|
+
) -> None:
|
|
196
|
+
"""Setup instrumentation with environment variable fallbacks.
|
|
197
|
+
|
|
198
|
+
This is a convenience wrapper around auto_instrument that reads from
|
|
199
|
+
environment variables if parameters aren't provided.
|
|
200
|
+
|
|
201
|
+
Args:
|
|
202
|
+
service_name: Service name (default: from env or 'default-service')
|
|
203
|
+
otlp_endpoint: OTLP endpoint (default: from env or 'localhost:47117')
|
|
204
|
+
tenant_id: Tenant ID (default: from env or 1)
|
|
205
|
+
project_id: Project ID (default: from env or 0)
|
|
206
|
+
capture_content: Capture LLM content (default: from env or True)
|
|
207
|
+
debug: Enable debug logging (default: from env or False)
|
|
208
|
+
"""
|
|
209
|
+
# Read from environment
|
|
210
|
+
service_name = service_name or os.getenv("AGENTREPLAY_SERVICE_NAME", "default-service")
|
|
211
|
+
otlp_endpoint = otlp_endpoint or os.getenv("AGENTREPLAY_OTLP_ENDPOINT", "localhost:47117")
|
|
212
|
+
|
|
213
|
+
if tenant_id is None:
|
|
214
|
+
tenant_id = int(os.getenv("AGENTREPLAY_TENANT_ID", "1"))
|
|
215
|
+
|
|
216
|
+
if project_id is None:
|
|
217
|
+
project_id = int(os.getenv("AGENTREPLAY_PROJECT_ID", "0"))
|
|
218
|
+
|
|
219
|
+
if capture_content is None:
|
|
220
|
+
capture_content = os.getenv("AGENTREPLAY_CAPTURE_CONTENT", "true").lower() in {
|
|
221
|
+
"1", "true", "yes"
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
if debug is None:
|
|
225
|
+
debug = os.getenv("AGENTREPLAY_DEBUG", "false").lower() in {"1", "true", "yes"}
|
|
226
|
+
|
|
227
|
+
auto_instrument(
|
|
228
|
+
service_name=service_name,
|
|
229
|
+
otlp_endpoint=otlp_endpoint,
|
|
230
|
+
tenant_id=tenant_id,
|
|
231
|
+
project_id=project_id,
|
|
232
|
+
capture_content=capture_content,
|
|
233
|
+
debug=debug,
|
|
234
|
+
)
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
__all__ = ["auto_instrument", "setup_instrumentation"]
|