prela 0.1.0__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.
- prela/__init__.py +394 -0
- prela/_version.py +3 -0
- prela/contrib/CLI.md +431 -0
- prela/contrib/README.md +118 -0
- prela/contrib/__init__.py +5 -0
- prela/contrib/cli.py +1063 -0
- prela/contrib/explorer.py +571 -0
- prela/core/__init__.py +64 -0
- prela/core/clock.py +98 -0
- prela/core/context.py +228 -0
- prela/core/replay.py +403 -0
- prela/core/sampler.py +178 -0
- prela/core/span.py +295 -0
- prela/core/tracer.py +498 -0
- prela/evals/__init__.py +94 -0
- prela/evals/assertions/README.md +484 -0
- prela/evals/assertions/__init__.py +78 -0
- prela/evals/assertions/base.py +90 -0
- prela/evals/assertions/multi_agent.py +625 -0
- prela/evals/assertions/semantic.py +223 -0
- prela/evals/assertions/structural.py +443 -0
- prela/evals/assertions/tool.py +380 -0
- prela/evals/case.py +370 -0
- prela/evals/n8n/__init__.py +69 -0
- prela/evals/n8n/assertions.py +450 -0
- prela/evals/n8n/runner.py +497 -0
- prela/evals/reporters/README.md +184 -0
- prela/evals/reporters/__init__.py +32 -0
- prela/evals/reporters/console.py +251 -0
- prela/evals/reporters/json.py +176 -0
- prela/evals/reporters/junit.py +278 -0
- prela/evals/runner.py +525 -0
- prela/evals/suite.py +316 -0
- prela/exporters/__init__.py +27 -0
- prela/exporters/base.py +189 -0
- prela/exporters/console.py +443 -0
- prela/exporters/file.py +322 -0
- prela/exporters/http.py +394 -0
- prela/exporters/multi.py +154 -0
- prela/exporters/otlp.py +388 -0
- prela/instrumentation/ANTHROPIC.md +297 -0
- prela/instrumentation/LANGCHAIN.md +480 -0
- prela/instrumentation/OPENAI.md +59 -0
- prela/instrumentation/__init__.py +49 -0
- prela/instrumentation/anthropic.py +1436 -0
- prela/instrumentation/auto.py +129 -0
- prela/instrumentation/base.py +436 -0
- prela/instrumentation/langchain.py +959 -0
- prela/instrumentation/llamaindex.py +719 -0
- prela/instrumentation/multi_agent/__init__.py +48 -0
- prela/instrumentation/multi_agent/autogen.py +357 -0
- prela/instrumentation/multi_agent/crewai.py +404 -0
- prela/instrumentation/multi_agent/langgraph.py +299 -0
- prela/instrumentation/multi_agent/models.py +203 -0
- prela/instrumentation/multi_agent/swarm.py +231 -0
- prela/instrumentation/n8n/__init__.py +68 -0
- prela/instrumentation/n8n/code_node.py +534 -0
- prela/instrumentation/n8n/models.py +336 -0
- prela/instrumentation/n8n/webhook.py +489 -0
- prela/instrumentation/openai.py +1198 -0
- prela/license.py +245 -0
- prela/replay/__init__.py +31 -0
- prela/replay/comparison.py +390 -0
- prela/replay/engine.py +1227 -0
- prela/replay/loader.py +231 -0
- prela/replay/result.py +196 -0
- prela-0.1.0.dist-info/METADATA +399 -0
- prela-0.1.0.dist-info/RECORD +71 -0
- prela-0.1.0.dist-info/WHEEL +4 -0
- prela-0.1.0.dist-info/entry_points.txt +2 -0
- prela-0.1.0.dist-info/licenses/LICENSE +190 -0
prela/__init__.py
ADDED
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
"""Prela - AI Agent Observability Platform SDK."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
import os
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
from prela._version import __version__
|
|
10
|
+
from prela.core.context import TraceContext, get_current_span, new_trace_context
|
|
11
|
+
from prela.core.sampler import (
|
|
12
|
+
AlwaysOffSampler,
|
|
13
|
+
AlwaysOnSampler,
|
|
14
|
+
BaseSampler,
|
|
15
|
+
ProbabilitySampler,
|
|
16
|
+
RateLimitingSampler,
|
|
17
|
+
)
|
|
18
|
+
from prela.core.span import Span, SpanEvent, SpanStatus, SpanType
|
|
19
|
+
from prela.core.tracer import Tracer, get_tracer, set_global_tracer, trace
|
|
20
|
+
from prela.exporters.base import BaseExporter, ExportResult
|
|
21
|
+
from prela.exporters.console import ConsoleExporter
|
|
22
|
+
from prela.exporters.file import FileExporter
|
|
23
|
+
from prela.exporters.http import HTTPExporter
|
|
24
|
+
from prela.exporters.multi import MultiExporter
|
|
25
|
+
|
|
26
|
+
# Optional exporters
|
|
27
|
+
try:
|
|
28
|
+
from prela.exporters.otlp import OTLPExporter
|
|
29
|
+
except ImportError:
|
|
30
|
+
OTLPExporter = None # type: ignore
|
|
31
|
+
from prela.instrumentation.auto import auto_instrument as _auto_instrument
|
|
32
|
+
|
|
33
|
+
__all__ = [
|
|
34
|
+
# Version
|
|
35
|
+
"__version__",
|
|
36
|
+
# Main API
|
|
37
|
+
"init",
|
|
38
|
+
"Tracer",
|
|
39
|
+
"get_tracer",
|
|
40
|
+
"trace",
|
|
41
|
+
# Span types
|
|
42
|
+
"Span",
|
|
43
|
+
"SpanEvent",
|
|
44
|
+
"SpanType",
|
|
45
|
+
"SpanStatus",
|
|
46
|
+
# Context
|
|
47
|
+
"TraceContext",
|
|
48
|
+
"get_current_span",
|
|
49
|
+
"new_trace_context",
|
|
50
|
+
# Sampling
|
|
51
|
+
"BaseSampler",
|
|
52
|
+
"AlwaysOnSampler",
|
|
53
|
+
"AlwaysOffSampler",
|
|
54
|
+
"ProbabilitySampler",
|
|
55
|
+
"RateLimitingSampler",
|
|
56
|
+
# Exporters
|
|
57
|
+
"BaseExporter",
|
|
58
|
+
"ConsoleExporter",
|
|
59
|
+
"FileExporter",
|
|
60
|
+
"HTTPExporter",
|
|
61
|
+
"MultiExporter",
|
|
62
|
+
"OTLPExporter",
|
|
63
|
+
"ExportResult",
|
|
64
|
+
# Auto-instrumentation
|
|
65
|
+
"auto_instrument",
|
|
66
|
+
]
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def init(
|
|
70
|
+
service_name: str | None = None,
|
|
71
|
+
exporter: str | BaseExporter | None = None,
|
|
72
|
+
auto_instrument: bool = True,
|
|
73
|
+
sample_rate: float | None = None,
|
|
74
|
+
capture_for_replay: bool = False,
|
|
75
|
+
project_id: str | None = None,
|
|
76
|
+
n8n_webhook_port: int | None = None,
|
|
77
|
+
n8n_webhook_host: str = "0.0.0.0",
|
|
78
|
+
**kwargs: Any,
|
|
79
|
+
) -> Tracer:
|
|
80
|
+
"""
|
|
81
|
+
Initialize Prela tracing with one line of code.
|
|
82
|
+
|
|
83
|
+
This is the primary entry point for the Prela SDK. It:
|
|
84
|
+
1. Creates a tracer with the specified configuration
|
|
85
|
+
2. Sets it as the global tracer
|
|
86
|
+
3. Auto-instruments detected LLM SDKs (Anthropic, OpenAI, etc.)
|
|
87
|
+
4. Optionally starts n8n webhook receiver for zero-code workflow tracing
|
|
88
|
+
5. Returns the tracer for manual span creation
|
|
89
|
+
|
|
90
|
+
After calling init(), all LLM SDK calls are automatically traced!
|
|
91
|
+
|
|
92
|
+
Args:
|
|
93
|
+
service_name: Name of your service (default: $PRELA_SERVICE_NAME or "default")
|
|
94
|
+
exporter: Where to send traces:
|
|
95
|
+
- "console": Pretty-print to console (default)
|
|
96
|
+
- "file": Write to JSONL file
|
|
97
|
+
- "http": Send to HTTP endpoint (Railway, cloud backend)
|
|
98
|
+
- BaseExporter instance: Custom exporter
|
|
99
|
+
- Default: $PRELA_EXPORTER or "console"
|
|
100
|
+
auto_instrument: Whether to auto-instrument detected libraries
|
|
101
|
+
(default: True, disable with $PRELA_AUTO_INSTRUMENT=false)
|
|
102
|
+
sample_rate: Sampling rate 0.0-1.0 (default: $PRELA_SAMPLE_RATE or 1.0)
|
|
103
|
+
capture_for_replay: Enable full replay data capture (default: False)
|
|
104
|
+
When enabled, captures complete request/response data including:
|
|
105
|
+
- LLM: Full prompts, responses, streaming chunks, model info
|
|
106
|
+
- Tools: Input args, output, side effects flag
|
|
107
|
+
- Retrieval: Queries, documents, scores, metadata
|
|
108
|
+
- Agents: System prompts, available tools, memory, config
|
|
109
|
+
Use for debugging, testing, and auditing. Increases storage costs.
|
|
110
|
+
project_id: Project ID for multi-tenant deployments (default: $PRELA_PROJECT_ID or None)
|
|
111
|
+
Used for:
|
|
112
|
+
- Organizing traces in multi-project deployments
|
|
113
|
+
- Filtering dashboards by project
|
|
114
|
+
- n8n webhook routing (?project={project_id})
|
|
115
|
+
n8n_webhook_port: Port for n8n webhook receiver (optional, default: None)
|
|
116
|
+
Set to enable n8n webhook-based tracing (e.g., 8787)
|
|
117
|
+
Example: n8n_webhook_port=8787
|
|
118
|
+
n8n_webhook_host: Host for n8n webhook receiver (default: "0.0.0.0")
|
|
119
|
+
Usually "0.0.0.0" for accepting external connections
|
|
120
|
+
**kwargs: Additional arguments passed to exporter
|
|
121
|
+
For ConsoleExporter: verbosity, color, show_timestamps
|
|
122
|
+
For FileExporter: directory, format, max_file_size_mb, rotate
|
|
123
|
+
For HTTPExporter: endpoint, api_key, bearer_token, compress, headers
|
|
124
|
+
|
|
125
|
+
Returns:
|
|
126
|
+
Configured Tracer instance (also set as global tracer)
|
|
127
|
+
|
|
128
|
+
Environment Variables:
|
|
129
|
+
PRELA_SERVICE_NAME: Default service name
|
|
130
|
+
PRELA_PROJECT_ID: Default project ID for multi-tenant setups
|
|
131
|
+
PRELA_EXPORTER: Default exporter ("console", "file", or "http")
|
|
132
|
+
PRELA_SAMPLE_RATE: Default sampling rate (0.0-1.0)
|
|
133
|
+
PRELA_CAPTURE_REPLAY: Enable replay capture ("true", "1", or "yes")
|
|
134
|
+
PRELA_AUTO_INSTRUMENT: Enable auto-instrumentation ("true" or "false")
|
|
135
|
+
PRELA_DEBUG: Enable debug logging ("true" or "false")
|
|
136
|
+
PRELA_TRACE_DIR: Directory for file exporter (default: ./traces)
|
|
137
|
+
PRELA_HTTP_ENDPOINT: HTTP endpoint for http exporter
|
|
138
|
+
PRELA_API_KEY: API key for http exporter
|
|
139
|
+
PRELA_N8N_WEBHOOK_PORT: Port for n8n webhook receiver (optional)
|
|
140
|
+
|
|
141
|
+
Example:
|
|
142
|
+
```python
|
|
143
|
+
import prela
|
|
144
|
+
|
|
145
|
+
# Simple initialization
|
|
146
|
+
prela.init(service_name="my-agent")
|
|
147
|
+
|
|
148
|
+
# All Anthropic/OpenAI calls now auto-traced!
|
|
149
|
+
from anthropic import Anthropic
|
|
150
|
+
client = Anthropic()
|
|
151
|
+
response = client.messages.create(
|
|
152
|
+
model="claude-sonnet-4-20250514",
|
|
153
|
+
max_tokens=1024,
|
|
154
|
+
messages=[{"role": "user", "content": "Hello!"}]
|
|
155
|
+
)
|
|
156
|
+
# Trace is automatically captured and exported
|
|
157
|
+
|
|
158
|
+
# Manual span creation
|
|
159
|
+
with prela.get_tracer().span("custom_operation") as span:
|
|
160
|
+
span.set_attribute("key", "value")
|
|
161
|
+
# Do work...
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Example with console exporter (verbose mode):
|
|
165
|
+
```python
|
|
166
|
+
import prela
|
|
167
|
+
|
|
168
|
+
prela.init(
|
|
169
|
+
service_name="my-agent",
|
|
170
|
+
exporter="console",
|
|
171
|
+
verbosity="verbose", # "minimal", "normal", or "verbose"
|
|
172
|
+
color=True,
|
|
173
|
+
show_timestamps=True
|
|
174
|
+
)
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Example with file exporter:
|
|
178
|
+
```python
|
|
179
|
+
import prela
|
|
180
|
+
|
|
181
|
+
prela.init(
|
|
182
|
+
service_name="my-agent",
|
|
183
|
+
exporter="file",
|
|
184
|
+
directory="./traces",
|
|
185
|
+
max_file_size_mb=100, # 100 MB per file
|
|
186
|
+
rotate=True
|
|
187
|
+
)
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Example with HTTP exporter (Railway deployment):
|
|
191
|
+
```python
|
|
192
|
+
import prela
|
|
193
|
+
|
|
194
|
+
prela.init(
|
|
195
|
+
service_name="my-agent",
|
|
196
|
+
exporter="http",
|
|
197
|
+
endpoint="https://prela-ingest-gateway-xxx.railway.app/v1/traces",
|
|
198
|
+
api_key="your-api-key", # Optional
|
|
199
|
+
compress=True # Enable gzip compression
|
|
200
|
+
)
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
Example with n8n webhook receiver:
|
|
204
|
+
```python
|
|
205
|
+
import prela
|
|
206
|
+
|
|
207
|
+
# Start webhook receiver on port 8787
|
|
208
|
+
prela.init(
|
|
209
|
+
service_name="n8n-workflows",
|
|
210
|
+
exporter="http",
|
|
211
|
+
endpoint="https://prela-ingest-gateway-xxx.railway.app/v1/traces",
|
|
212
|
+
n8n_webhook_port=8787
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
# Now configure n8n HTTP Request node to POST to:
|
|
216
|
+
# http://your-server:8787/webhook
|
|
217
|
+
# Body: {"workflow": "{{ $workflow }}", "execution": "{{ $execution }}", ...}
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
Example with custom exporter:
|
|
221
|
+
```python
|
|
222
|
+
from prela import init, BaseExporter, ExportResult
|
|
223
|
+
|
|
224
|
+
class MyExporter(BaseExporter):
|
|
225
|
+
def export(self, spans):
|
|
226
|
+
# Send to your backend
|
|
227
|
+
return ExportResult.SUCCESS
|
|
228
|
+
|
|
229
|
+
init(service_name="my-agent", exporter=MyExporter())
|
|
230
|
+
```
|
|
231
|
+
"""
|
|
232
|
+
# Read from environment variables with fallbacks
|
|
233
|
+
service_name = service_name or os.getenv("PRELA_SERVICE_NAME", "default")
|
|
234
|
+
project_id = project_id or os.getenv("PRELA_PROJECT_ID") # Optional, defaults to None
|
|
235
|
+
exporter_name = exporter or os.getenv("PRELA_EXPORTER", "console")
|
|
236
|
+
sample_rate = (
|
|
237
|
+
sample_rate
|
|
238
|
+
if sample_rate is not None
|
|
239
|
+
else float(os.getenv("PRELA_SAMPLE_RATE", "1.0"))
|
|
240
|
+
)
|
|
241
|
+
auto_instrument_enabled = auto_instrument and os.getenv(
|
|
242
|
+
"PRELA_AUTO_INSTRUMENT", "true"
|
|
243
|
+
).lower() not in ("false", "0", "no")
|
|
244
|
+
debug = os.getenv("PRELA_DEBUG", "false").lower() in ("true", "1", "yes")
|
|
245
|
+
|
|
246
|
+
# n8n webhook configuration
|
|
247
|
+
n8n_webhook_port = n8n_webhook_port or (
|
|
248
|
+
int(os.getenv("PRELA_N8N_WEBHOOK_PORT"))
|
|
249
|
+
if os.getenv("PRELA_N8N_WEBHOOK_PORT")
|
|
250
|
+
else None
|
|
251
|
+
)
|
|
252
|
+
|
|
253
|
+
# Configure debug logging if requested
|
|
254
|
+
if debug:
|
|
255
|
+
logging.basicConfig(
|
|
256
|
+
level=logging.DEBUG, format="%(asctime)s - %(name)s - %(message)s"
|
|
257
|
+
)
|
|
258
|
+
logger = logging.getLogger("prela")
|
|
259
|
+
logger.setLevel(logging.DEBUG)
|
|
260
|
+
|
|
261
|
+
# Create sampler based on sample rate
|
|
262
|
+
if sample_rate >= 1.0:
|
|
263
|
+
sampler = AlwaysOnSampler()
|
|
264
|
+
elif sample_rate <= 0.0:
|
|
265
|
+
sampler = AlwaysOffSampler()
|
|
266
|
+
else:
|
|
267
|
+
sampler = ProbabilitySampler(rate=sample_rate)
|
|
268
|
+
|
|
269
|
+
# Create exporter
|
|
270
|
+
if isinstance(exporter_name, BaseExporter):
|
|
271
|
+
# Custom exporter instance provided
|
|
272
|
+
exporter_instance = exporter_name
|
|
273
|
+
elif exporter_name == "console":
|
|
274
|
+
exporter_instance = ConsoleExporter(**kwargs)
|
|
275
|
+
elif exporter_name == "file":
|
|
276
|
+
directory = kwargs.get("directory", os.getenv("PRELA_TRACE_DIR", "./traces"))
|
|
277
|
+
# Remove directory from kwargs to avoid duplication
|
|
278
|
+
file_kwargs = {k: v for k, v in kwargs.items() if k != "directory"}
|
|
279
|
+
exporter_instance = FileExporter(directory=directory, **file_kwargs)
|
|
280
|
+
elif exporter_name == "http":
|
|
281
|
+
endpoint = kwargs.get("endpoint", os.getenv("PRELA_HTTP_ENDPOINT"))
|
|
282
|
+
if not endpoint:
|
|
283
|
+
raise ValueError(
|
|
284
|
+
"HTTP exporter requires 'endpoint' parameter or PRELA_HTTP_ENDPOINT env var"
|
|
285
|
+
)
|
|
286
|
+
api_key = kwargs.get("api_key", os.getenv("PRELA_API_KEY"))
|
|
287
|
+
# Remove endpoint and api_key from kwargs to avoid duplication
|
|
288
|
+
http_kwargs = {k: v for k, v in kwargs.items() if k not in ("endpoint", "api_key")}
|
|
289
|
+
if api_key:
|
|
290
|
+
http_kwargs["api_key"] = api_key
|
|
291
|
+
exporter_instance = HTTPExporter(endpoint=endpoint, **http_kwargs)
|
|
292
|
+
else:
|
|
293
|
+
raise ValueError(
|
|
294
|
+
f"Unknown exporter: {exporter_name}. "
|
|
295
|
+
f"Use 'console', 'file', 'http', or provide a BaseExporter instance."
|
|
296
|
+
)
|
|
297
|
+
|
|
298
|
+
# Read PRELA_CAPTURE_REPLAY environment variable
|
|
299
|
+
capture_replay = capture_for_replay
|
|
300
|
+
if not capture_replay:
|
|
301
|
+
env_val = os.getenv("PRELA_CAPTURE_REPLAY", "").lower()
|
|
302
|
+
capture_replay = env_val in ("true", "1", "yes")
|
|
303
|
+
|
|
304
|
+
# Create tracer
|
|
305
|
+
tracer = Tracer(
|
|
306
|
+
service_name=service_name,
|
|
307
|
+
exporter=exporter_instance,
|
|
308
|
+
sampler=sampler,
|
|
309
|
+
capture_for_replay=capture_replay,
|
|
310
|
+
)
|
|
311
|
+
|
|
312
|
+
# Set as global tracer
|
|
313
|
+
tracer.set_global()
|
|
314
|
+
|
|
315
|
+
# Auto-instrument detected libraries
|
|
316
|
+
if auto_instrument_enabled:
|
|
317
|
+
instrumented = _auto_instrument(tracer)
|
|
318
|
+
if debug and instrumented:
|
|
319
|
+
logger = logging.getLogger("prela")
|
|
320
|
+
logger.debug(f"Auto-instrumented: {', '.join(instrumented)}")
|
|
321
|
+
|
|
322
|
+
# Start n8n webhook receiver if configured
|
|
323
|
+
if n8n_webhook_port:
|
|
324
|
+
try:
|
|
325
|
+
from prela.instrumentation.n8n.webhook import N8nWebhookHandler
|
|
326
|
+
import threading
|
|
327
|
+
|
|
328
|
+
webhook_handler = N8nWebhookHandler(
|
|
329
|
+
tracer=tracer, port=n8n_webhook_port, host=n8n_webhook_host
|
|
330
|
+
)
|
|
331
|
+
|
|
332
|
+
# Start webhook handler in background thread
|
|
333
|
+
webhook_thread = threading.Thread(
|
|
334
|
+
target=webhook_handler.start_background,
|
|
335
|
+
daemon=True,
|
|
336
|
+
name="n8n-webhook-handler",
|
|
337
|
+
)
|
|
338
|
+
webhook_thread.start()
|
|
339
|
+
|
|
340
|
+
if debug:
|
|
341
|
+
logger = logging.getLogger("prela")
|
|
342
|
+
logger.debug(
|
|
343
|
+
f"n8n webhook receiver started on {n8n_webhook_host}:{n8n_webhook_port}"
|
|
344
|
+
)
|
|
345
|
+
|
|
346
|
+
# Store references for cleanup (optional future use)
|
|
347
|
+
tracer._n8n_webhook_handler = webhook_handler # type: ignore
|
|
348
|
+
tracer._n8n_webhook_thread = webhook_thread # type: ignore
|
|
349
|
+
|
|
350
|
+
except Exception as e:
|
|
351
|
+
# Log warning but don't fail initialization
|
|
352
|
+
logger = logging.getLogger("prela")
|
|
353
|
+
logger.warning(f"Failed to start n8n webhook receiver: {e}")
|
|
354
|
+
|
|
355
|
+
return tracer
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
def auto_instrument(tracer: Tracer | None = None) -> list[str]:
|
|
359
|
+
"""
|
|
360
|
+
Manually trigger auto-instrumentation.
|
|
361
|
+
|
|
362
|
+
This is useful if you want to control when instrumentation happens,
|
|
363
|
+
or if you disabled auto-instrumentation in init() and want to enable
|
|
364
|
+
it later.
|
|
365
|
+
|
|
366
|
+
Args:
|
|
367
|
+
tracer: Tracer instance to use (default: global tracer from init())
|
|
368
|
+
|
|
369
|
+
Returns:
|
|
370
|
+
List of instrumented library names (e.g., ["anthropic", "openai"])
|
|
371
|
+
|
|
372
|
+
Raises:
|
|
373
|
+
RuntimeError: If no tracer is provided and no global tracer is set
|
|
374
|
+
|
|
375
|
+
Example:
|
|
376
|
+
```python
|
|
377
|
+
import prela
|
|
378
|
+
|
|
379
|
+
# Initialize without auto-instrumentation
|
|
380
|
+
prela.init(service_name="my-app", auto_instrument=False)
|
|
381
|
+
|
|
382
|
+
# Later, manually trigger instrumentation
|
|
383
|
+
instrumented = prela.auto_instrument()
|
|
384
|
+
print(f"Instrumented: {instrumented}")
|
|
385
|
+
```
|
|
386
|
+
"""
|
|
387
|
+
if tracer is None:
|
|
388
|
+
tracer = get_tracer()
|
|
389
|
+
if tracer is None:
|
|
390
|
+
raise RuntimeError(
|
|
391
|
+
"No global tracer set. Call prela.init() first or provide a tracer."
|
|
392
|
+
)
|
|
393
|
+
|
|
394
|
+
return _auto_instrument(tracer)
|
prela/_version.py
ADDED