mantisdk 0.1.2__py3-none-any.whl → 0.1.3__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.
mantisdk/__init__.py CHANGED
@@ -1,6 +1,6 @@
1
1
  # Copyright (c) Microsoft. All rights reserved.
2
2
 
3
- __version__ = "0.1.2"
3
+ __version__ = "0.1.3"
4
4
 
5
5
  from .adapter import *
6
6
  from .algorithm import *
@@ -3,25 +3,29 @@
3
3
  """Standalone tracing module for MantisDK.
4
4
 
5
5
  This module provides a "one-liner" entry point for instrumenting applications
6
- with OpenTelemetry, compatible with OpenInference and AgentOps ecosystems,
6
+ with OpenTelemetry, compatible with OpenInference ecosystem,
7
7
  while natively supporting export to Mantis Insight.
8
8
 
9
9
  Example usage::
10
10
 
11
- import mantisdk.tracing_claude as tracing
11
+ import mantisdk.tracing as tracing
12
12
 
13
13
  # Auto-detect Insight from environment variables
14
14
  tracing.init()
15
15
 
16
- # Use context managers for manual spans
17
- with tracing.trace("my-workflow"):
18
- with tracing.span("step-1"):
19
- do_work()
20
-
21
- # Use decorators
16
+ # Use as a decorator (auto-captures input/output)
22
17
  @tracing.trace
23
- def my_function():
24
- pass
18
+ def my_function(query: str) -> dict:
19
+ return {"result": query.upper()}
20
+
21
+ # Use as a context manager (explicit input/output)
22
+ with tracing.trace("my-workflow", input=query) as span:
23
+ result = do_work()
24
+ span.set_attribute(tracing.semconv.TRACE_OUTPUT, result)
25
+
26
+ # Use semantic conventions for rich metadata
27
+ span.set_attribute(tracing.semconv.USER_ID, "user-123")
28
+ span.set_attribute(tracing.semconv.SESSION_ID, "session-456")
25
29
 
26
30
  # Ensure spans are flushed on shutdown
27
31
  tracing.shutdown()
@@ -34,7 +38,8 @@ Environment variables for Insight auto-detect:
34
38
  """
35
39
 
36
40
  from .init import init, instrument, shutdown, flush
37
- from .api import trace, span, tool, atrace, aspan
41
+ from .api import trace, span, tool, atrace, aspan, get_current_span
42
+ from . import semconv
38
43
 
39
44
  # Re-export exporter factory for explicit configuration
40
45
  from .exporters.insight import insight as insight_exporter
@@ -45,13 +50,17 @@ __all__ = [
45
50
  "instrument",
46
51
  "shutdown",
47
52
  "flush",
48
- # Context managers (sync)
53
+ # Context managers / decorators (sync)
49
54
  "trace",
50
55
  "span",
51
56
  "tool",
52
57
  # Context managers (async)
53
58
  "atrace",
54
59
  "aspan",
60
+ # Span utilities
61
+ "get_current_span",
62
+ # Semantic conventions
63
+ "semconv",
55
64
  # Exporter factory
56
65
  "insight_exporter",
57
66
  ]
mantisdk/tracing/api.py CHANGED
@@ -14,12 +14,16 @@ from __future__ import annotations
14
14
 
15
15
  import asyncio
16
16
  import functools
17
+ import inspect
18
+ import json
17
19
  import logging
18
20
  from contextlib import asynccontextmanager, contextmanager
19
21
  from typing import Any, AsyncGenerator, Callable, Generator, Optional, TypeVar, Union
20
22
 
21
- from opentelemetry import trace
22
- from opentelemetry.trace import Span, SpanKind, Status, StatusCode
23
+ from opentelemetry import trace as otel_trace
24
+ from opentelemetry.trace import Span, SpanKind, Status, StatusCode, Tracer
25
+
26
+ from . import semconv
23
27
 
24
28
  logger = logging.getLogger(__name__)
25
29
 
@@ -30,69 +34,246 @@ F = TypeVar("F", bound=Callable[..., Any])
30
34
  TRACER_NAME = "mantisdk.tracing"
31
35
 
32
36
 
33
- def _get_tracer() -> trace.Tracer:
34
- """Get the MantisDK tracer instance."""
35
- return trace.get_tracer(TRACER_NAME)
37
+ # =============================================================================
38
+ # Serialization helpers for I/O capture
39
+ # =============================================================================
40
+
41
+
42
+ def _safe_serialize(value: Any) -> Any:
43
+ """Recursively serialize a value to JSON-compatible format."""
44
+ if value is None or isinstance(value, (bool, int, float, str)):
45
+ return value
46
+ if isinstance(value, (list, tuple)):
47
+ return [_safe_serialize(v) for v in value]
48
+ if isinstance(value, dict):
49
+ return {str(k): _safe_serialize(v) for k, v in value.items()}
50
+ # Fallback for complex objects (Pydantic models, dataclasses, etc.)
51
+ if hasattr(value, "model_dump"):
52
+ return _safe_serialize(value.model_dump())
53
+ if hasattr(value, "__dict__"):
54
+ return _safe_serialize(vars(value))
55
+ return str(value)
56
+
57
+
58
+ def _serialize_value(value: Any) -> str:
59
+ """Safely serialize a value to a JSON string for span attributes."""
60
+ if value is None:
61
+ return "null"
62
+ if isinstance(value, str):
63
+ return value
64
+ if isinstance(value, (bool, int, float)):
65
+ return json.dumps(value)
66
+ try:
67
+ return json.dumps(_safe_serialize(value))
68
+ except Exception:
69
+ return str(value)
70
+
71
+
72
+ def _capture_function_input(fn: Callable[..., Any], args: tuple[Any, ...], kwargs: dict[str, Any]) -> str:
73
+ """Capture function arguments as a JSON string."""
74
+ try:
75
+ sig = inspect.signature(fn)
76
+ bound = sig.bind(*args, **kwargs)
77
+ bound.apply_defaults()
78
+
79
+ # Filter out 'self' and 'cls' parameters
80
+ input_dict = {
81
+ k: _safe_serialize(v)
82
+ for k, v in bound.arguments.items()
83
+ if k not in ("self", "cls")
84
+ }
36
85
 
86
+ return json.dumps(input_dict) if input_dict else "{}"
87
+ except Exception:
88
+ # Fallback: simple representation
89
+ return json.dumps({
90
+ "args": [str(a) for a in args],
91
+ "kwargs": {k: str(v) for k, v in kwargs.items()}
92
+ })
37
93
 
38
- @contextmanager
39
- def trace(
40
- name: str,
41
- *,
42
- kind: SpanKind = SpanKind.INTERNAL,
43
- attributes: Optional[dict[str, Any]] = None,
44
- record_exception: bool = True,
45
- set_status_on_exception: bool = True,
46
- **extra_attributes: Any,
47
- ) -> Generator[Span, None, None]:
48
- """Context manager to create a trace (root span).
49
94
 
50
- This creates a new span that will be the root of a trace tree.
51
- Child spans created within this context will be linked to this root.
95
+ def _get_tracer() -> Tracer:
96
+ """Get the MantisDK tracer instance."""
97
+ return otel_trace.get_tracer(TRACER_NAME)
52
98
 
53
- Args:
54
- name: The name of the trace/span.
55
- kind: The span kind (default: INTERNAL).
56
- attributes: Dictionary of attributes to set on the span.
57
- record_exception: If True, exceptions are recorded on the span.
58
- set_status_on_exception: If True, span status is set to ERROR on exception.
59
- **extra_attributes: Additional attributes as keyword arguments.
60
99
 
61
- Yields:
62
- The OpenTelemetry Span object.
100
+ class trace:
101
+ """Create a trace span - works as both a decorator and context manager.
63
102
 
64
- Example::
103
+ As a decorator, automatically captures function inputs and outputs::
65
104
 
66
- import mantisdk.tracing_claude as tracing
105
+ @tracing.trace
106
+ def my_function(query: str) -> dict:
107
+ return {"result": query.upper()}
108
+
109
+ @tracing.trace(name="custom-name", capture_output=False)
110
+ def another_function(data):
111
+ process(data)
67
112
 
68
- tracing.init()
113
+ As a context manager, allows explicit input/output control::
69
114
 
70
- with tracing.trace("my-workflow", user_id="123") as span:
71
- span.set_attribute("step", "preprocessing")
115
+ with tracing.trace("my-workflow", input=query) as span:
72
116
  result = do_work()
73
- span.set_attribute("result_count", len(result))
117
+ span.set_attribute(tracing.semconv.TRACE_OUTPUT, result)
118
+
119
+ Args:
120
+ name_or_func: Either the span name (str) or the function to decorate.
121
+ name: Explicit span name (for decorator with custom name).
122
+ input: Input value to capture (context manager mode).
123
+ kind: The span kind (default: INTERNAL).
124
+ attributes: Dictionary of attributes to set on the span.
125
+ capture_input: Auto-capture function input (decorator mode, default: True).
126
+ capture_output: Auto-capture function output (decorator mode, default: True).
127
+ record_exception: If True, exceptions are recorded on the span.
128
+ set_status_on_exception: If True, span status is set to ERROR on exception.
74
129
  """
75
- tracer = _get_tracer()
76
- all_attributes = {**(attributes or {}), **extra_attributes}
77
130
 
78
- with tracer.start_as_current_span(
79
- name=name,
80
- kind=kind,
81
- attributes=all_attributes if all_attributes else None,
82
- record_exception=record_exception,
83
- set_status_on_exception=set_status_on_exception,
84
- ) as otel_span:
131
+ def __init__(
132
+ self,
133
+ name_or_func: Optional[Union[str, Callable[..., Any]]] = None,
134
+ *,
135
+ name: Optional[str] = None,
136
+ input: Optional[Any] = None,
137
+ kind: SpanKind = SpanKind.INTERNAL,
138
+ attributes: Optional[dict[str, Any]] = None,
139
+ capture_input: bool = True,
140
+ capture_output: bool = True,
141
+ record_exception: bool = True,
142
+ set_status_on_exception: bool = True,
143
+ ):
144
+ self._name_or_func = name_or_func
145
+ self._explicit_name = name
146
+ self._input = input
147
+ self._kind = kind
148
+ self._attributes = attributes
149
+ self._capture_input = capture_input
150
+ self._capture_output = capture_output
151
+ self._record_exception = record_exception
152
+ self._set_status_on_exception = set_status_on_exception
153
+ self._span: Optional[Span] = None
154
+ self._token: Optional[Any] = None
155
+
156
+ # If called as @trace without parentheses, name_or_func is the function
157
+ if callable(name_or_func):
158
+ self._func = name_or_func
159
+ self._span_name = name or name_or_func.__name__
160
+ else:
161
+ self._func = None
162
+ self._span_name = name_or_func or name or "trace"
163
+
164
+ def __call__(self, *args: Any, **kwargs: Any) -> Any:
165
+ """Handle decorator invocation."""
166
+ # If we already have a function, this is the actual call
167
+ if self._func is not None:
168
+ return self._invoke_decorated(self._func, args, kwargs)
169
+
170
+ # If first arg is a callable, we're being used as @trace(...) decorator
171
+ if args and callable(args[0]) and not kwargs:
172
+ func = args[0]
173
+ self._func = func
174
+ self._span_name = self._explicit_name or func.__name__
175
+
176
+ # Return a wrapper that will be called when the function is invoked
177
+ if asyncio.iscoroutinefunction(func):
178
+ @functools.wraps(func)
179
+ async def async_wrapper(*a: Any, **kw: Any) -> Any:
180
+ return await self._invoke_decorated_async(func, a, kw)
181
+ return async_wrapper
182
+ else:
183
+ @functools.wraps(func)
184
+ def sync_wrapper(*a: Any, **kw: Any) -> Any:
185
+ return self._invoke_decorated(func, a, kw)
186
+ return sync_wrapper
187
+
188
+ raise TypeError("trace() requires a name string or a function")
189
+
190
+ def _invoke_decorated(self, func: Callable[..., Any], args: tuple[Any, ...], kwargs: dict[str, Any]) -> Any:
191
+ """Invoke a decorated sync function with tracing."""
192
+ tracer = _get_tracer()
193
+
194
+ with tracer.start_as_current_span(
195
+ name=self._span_name,
196
+ kind=self._kind,
197
+ attributes=self._attributes,
198
+ record_exception=self._record_exception,
199
+ set_status_on_exception=self._set_status_on_exception,
200
+ ) as span:
201
+ # Capture input
202
+ if self._capture_input:
203
+ input_val = _capture_function_input(func, args, kwargs)
204
+ span.set_attribute(semconv.OBSERVATION_INPUT, input_val)
205
+
206
+ result = func(*args, **kwargs)
207
+
208
+ # Capture output
209
+ if self._capture_output:
210
+ span.set_attribute(semconv.OBSERVATION_OUTPUT, _serialize_value(result))
211
+
212
+ return result
213
+
214
+ async def _invoke_decorated_async(self, func: Callable[..., Any], args: tuple[Any, ...], kwargs: dict[str, Any]) -> Any:
215
+ """Invoke a decorated async function with tracing."""
216
+ tracer = _get_tracer()
217
+
218
+ with tracer.start_as_current_span(
219
+ name=self._span_name,
220
+ kind=self._kind,
221
+ attributes=self._attributes,
222
+ record_exception=self._record_exception,
223
+ set_status_on_exception=self._set_status_on_exception,
224
+ ) as span:
225
+ # Capture input
226
+ if self._capture_input:
227
+ input_val = _capture_function_input(func, args, kwargs)
228
+ span.set_attribute(semconv.OBSERVATION_INPUT, input_val)
229
+
230
+ result = await func(*args, **kwargs)
231
+
232
+ # Capture output
233
+ if self._capture_output:
234
+ span.set_attribute(semconv.OBSERVATION_OUTPUT, _serialize_value(result))
235
+
236
+ return result
237
+
238
+ def __enter__(self) -> Span:
239
+ """Context manager entry - start the span."""
240
+ tracer = _get_tracer()
241
+ self._span = tracer.start_span(
242
+ name=self._span_name,
243
+ kind=self._kind,
244
+ attributes=self._attributes,
245
+ record_exception=self._record_exception,
246
+ set_status_on_exception=self._set_status_on_exception,
247
+ )
248
+ # Store the context manager to properly exit later
249
+ self._use_span_cm = otel_trace.use_span(self._span, end_on_exit=False)
250
+ self._use_span_cm.__enter__()
251
+
252
+ # Set input if provided
253
+ if self._input is not None:
254
+ self._span.set_attribute(semconv.TRACE_INPUT, _serialize_value(self._input))
255
+
256
+ return self._span
257
+
258
+ def __exit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None:
259
+ """Context manager exit - end the span."""
85
260
  try:
86
- yield otel_span
87
- except Exception as e:
88
- # Span context manager handles recording; we just re-raise
89
- raise
261
+ if self._span is not None:
262
+ if exc_val is not None and self._record_exception:
263
+ self._span.record_exception(exc_val)
264
+ if exc_val is not None and self._set_status_on_exception:
265
+ self._span.set_status(Status(StatusCode.ERROR, str(exc_val)))
266
+ self._span.end()
267
+ finally:
268
+ if hasattr(self, '_use_span_cm') and self._use_span_cm is not None:
269
+ self._use_span_cm.__exit__(exc_type, exc_val, exc_tb)
90
270
 
91
271
 
92
272
  @contextmanager
93
273
  def span(
94
274
  name: str,
95
275
  *,
276
+ input: Optional[Any] = None,
96
277
  kind: SpanKind = SpanKind.INTERNAL,
97
278
  attributes: Optional[dict[str, Any]] = None,
98
279
  record_exception: bool = True,
@@ -106,6 +287,7 @@ def span(
106
287
 
107
288
  Args:
108
289
  name: The name of the span.
290
+ input: Input value to capture (displayed in Insight UI).
109
291
  kind: The span kind (default: INTERNAL).
110
292
  attributes: Dictionary of attributes to set on the span.
111
293
  record_exception: If True, exceptions are recorded on the span.
@@ -117,12 +299,12 @@ def span(
117
299
 
118
300
  Example::
119
301
 
120
- import mantisdk.tracing_claude as tracing
302
+ import mantisdk.tracing as tracing
121
303
 
122
304
  with tracing.trace("my-workflow"):
123
- with tracing.span("step.load_data", dataset="training") as s:
305
+ with tracing.span("step.load_data", input=dataset_name) as s:
124
306
  data = load_data()
125
- s.set_attribute("rows", len(data))
307
+ s.set_attribute(tracing.semconv.OBSERVATION_OUTPUT, str(len(data)))
126
308
 
127
309
  with tracing.span("step.process"):
128
310
  process(data)
@@ -137,6 +319,9 @@ def span(
137
319
  record_exception=record_exception,
138
320
  set_status_on_exception=set_status_on_exception,
139
321
  ) as otel_span:
322
+ # Set input if provided
323
+ if input is not None:
324
+ otel_span.set_attribute(semconv.OBSERVATION_INPUT, _serialize_value(input))
140
325
  try:
141
326
  yield otel_span
142
327
  except Exception:
@@ -147,6 +332,7 @@ def span(
147
332
  def tool(
148
333
  name: str,
149
334
  *,
335
+ input: Optional[Any] = None,
150
336
  tool_name: Optional[str] = None,
151
337
  attributes: Optional[dict[str, Any]] = None,
152
338
  record_exception: bool = True,
@@ -160,6 +346,7 @@ def tool(
160
346
 
161
347
  Args:
162
348
  name: The span name (often the function/tool name).
349
+ input: Input value to capture (displayed in Insight UI).
163
350
  tool_name: Explicit tool name attribute (defaults to name).
164
351
  attributes: Dictionary of attributes to set on the span.
165
352
  record_exception: If True, exceptions are recorded on the span.
@@ -171,11 +358,11 @@ def tool(
171
358
 
172
359
  Example::
173
360
 
174
- import mantisdk.tracing_claude as tracing
361
+ import mantisdk.tracing as tracing
175
362
 
176
- with tracing.tool("search_database", query="SELECT *") as s:
363
+ with tracing.tool("search_database", input=query) as s:
177
364
  results = db.execute(query)
178
- s.set_attribute("result_count", len(results))
365
+ s.set_attribute(tracing.semconv.OBSERVATION_OUTPUT, str(len(results)))
179
366
  """
180
367
  tracer = _get_tracer()
181
368
  all_attributes = {
@@ -192,6 +379,9 @@ def tool(
192
379
  record_exception=record_exception,
193
380
  set_status_on_exception=set_status_on_exception,
194
381
  ) as otel_span:
382
+ # Set input if provided
383
+ if input is not None:
384
+ otel_span.set_attribute(semconv.OBSERVATION_INPUT, _serialize_value(input))
195
385
  try:
196
386
  yield otel_span
197
387
  except Exception:
@@ -202,6 +392,7 @@ def tool(
202
392
  async def atrace(
203
393
  name: str,
204
394
  *,
395
+ input: Optional[Any] = None,
205
396
  kind: SpanKind = SpanKind.INTERNAL,
206
397
  attributes: Optional[dict[str, Any]] = None,
207
398
  record_exception: bool = True,
@@ -214,6 +405,7 @@ async def atrace(
214
405
 
215
406
  Args:
216
407
  name: The name of the trace/span.
408
+ input: Input value to capture (displayed in Insight UI).
217
409
  kind: The span kind (default: INTERNAL).
218
410
  attributes: Dictionary of attributes to set on the span.
219
411
  record_exception: If True, exceptions are recorded on the span.
@@ -225,10 +417,11 @@ async def atrace(
225
417
 
226
418
  Example::
227
419
 
228
- import mantisdk.tracing_claude as tracing
420
+ import mantisdk.tracing as tracing
229
421
 
230
- async with tracing.atrace("my-async-workflow") as span:
422
+ async with tracing.atrace("my-async-workflow", input=query) as span:
231
423
  result = await async_operation()
424
+ span.set_attribute(tracing.semconv.TRACE_OUTPUT, result)
232
425
  """
233
426
  tracer = _get_tracer()
234
427
  all_attributes = {**(attributes or {}), **extra_attributes}
@@ -240,6 +433,9 @@ async def atrace(
240
433
  record_exception=record_exception,
241
434
  set_status_on_exception=set_status_on_exception,
242
435
  ) as otel_span:
436
+ # Set input if provided
437
+ if input is not None:
438
+ otel_span.set_attribute(semconv.TRACE_INPUT, _serialize_value(input))
243
439
  try:
244
440
  yield otel_span
245
441
  except Exception:
@@ -250,6 +446,7 @@ async def atrace(
250
446
  async def aspan(
251
447
  name: str,
252
448
  *,
449
+ input: Optional[Any] = None,
253
450
  kind: SpanKind = SpanKind.INTERNAL,
254
451
  attributes: Optional[dict[str, Any]] = None,
255
452
  record_exception: bool = True,
@@ -262,6 +459,7 @@ async def aspan(
262
459
 
263
460
  Args:
264
461
  name: The name of the span.
462
+ input: Input value to capture (displayed in Insight UI).
265
463
  kind: The span kind (default: INTERNAL).
266
464
  attributes: Dictionary of attributes to set on the span.
267
465
  record_exception: If True, exceptions are recorded on the span.
@@ -273,12 +471,12 @@ async def aspan(
273
471
 
274
472
  Example::
275
473
 
276
- import mantisdk.tracing_claude as tracing
474
+ import mantisdk.tracing as tracing
277
475
 
278
- async with tracing.atrace("workflow"):
476
+ async with tracing.atrace("workflow", input=query):
279
477
  async with tracing.aspan("fetch_data") as s:
280
478
  data = await fetch()
281
- s.set_attribute("size", len(data))
479
+ s.set_attribute(tracing.semconv.OBSERVATION_OUTPUT, str(len(data)))
282
480
  """
283
481
  tracer = _get_tracer()
284
482
  all_attributes = {**(attributes or {}), **extra_attributes}
@@ -290,6 +488,9 @@ async def aspan(
290
488
  record_exception=record_exception,
291
489
  set_status_on_exception=set_status_on_exception,
292
490
  ) as otel_span:
491
+ # Set input if provided
492
+ if input is not None:
493
+ otel_span.set_attribute(semconv.OBSERVATION_INPUT, _serialize_value(input))
293
494
  try:
294
495
  yield otel_span
295
496
  except Exception:
@@ -537,7 +738,7 @@ def get_current_span() -> Span:
537
738
  span = tracing.get_current_span()
538
739
  span.set_attribute("inner_data", "value")
539
740
  """
540
- return trace.get_current_span()
741
+ return otel_trace.get_current_span()
541
742
 
542
743
 
543
744
  # Convenience aliases for decorator-style usage
mantisdk/tracing/init.py CHANGED
@@ -35,8 +35,7 @@ def init(
35
35
  *,
36
36
  trace_name: Optional[str] = None,
37
37
  service_name: Optional[str] = None,
38
- instrument_default: bool = True,
39
- instrument_agentops: bool = False,
38
+ instrument_default: bool = False,
40
39
  exporters: Optional[List[SpanExporter]] = None,
41
40
  trace_config: Optional["TraceConfig"] = None,
42
41
  force: bool = False,
@@ -55,13 +54,11 @@ def init(
55
54
  - If force=True, replaces the existing TracerProvider.
56
55
 
57
56
  Args:
58
- trace_name: Optional name for the trace (mostly for AgentOps compatibility).
57
+ trace_name: Optional name for the trace.
59
58
  service_name: Name of the service (mapped to resource attributes).
60
59
  Defaults to "mantisdk-tracing".
61
60
  instrument_default: Whether to automatically instrument the "core set"
62
61
  of libraries (OpenAI, Anthropic, LangChain, LlamaIndex) if installed.
63
- instrument_agentops: Whether to enable AgentOps helpers (decorators)
64
- without exporting to AgentOps platform.
65
62
  exporters: List of custom OpenTelemetry SpanExporters. If None and
66
63
  Insight env vars are configured, auto-creates an Insight exporter.
67
64
  trace_config: OpenInference TraceConfig for controlling capture behavior
@@ -69,7 +66,6 @@ def init(
69
66
  force: If True, replaces any existing global TracerProvider. If False
70
67
  (default), reuses the existing provider and appends processors.
71
68
  integrations: Dictionary for fine-grained control over integrations.
72
- Example: {"agentops": {"enabled": True, "helpers_only": True}}
73
69
 
74
70
  Example::
75
71
 
@@ -143,9 +139,6 @@ def init(
143
139
  if instrument_default:
144
140
  instrument()
145
141
 
146
- if instrument_agentops:
147
- _setup_agentops_helpers(integrations)
148
-
149
142
  _initialized = True
150
143
  logger.info("MantisDK tracing initialized successfully")
151
144
 
@@ -336,26 +329,6 @@ def _get_exporter_id(exporter: SpanExporter) -> str:
336
329
  return class_name
337
330
 
338
331
 
339
- def _setup_agentops_helpers(integrations: Optional[Dict[str, Any]] = None) -> None:
340
- """Enable AgentOps helpers (decorators) without AgentOps export.
341
-
342
- This sets up AgentOps instrumentation in "helpers only" mode,
343
- where spans are created but exported through MantisDK's exporter
344
- rather than AgentOps's backend.
345
- """
346
- config = (integrations or {}).get("agentops", {})
347
- if not config.get("enabled", True):
348
- return
349
-
350
- try:
351
- import agentops
352
- # AgentOps init with no API key = helpers only mode
353
- # The spans will go through our TracerProvider
354
- logger.debug("AgentOps helpers mode enabled")
355
- except ImportError:
356
- logger.debug("AgentOps not installed, skipping helpers setup")
357
-
358
-
359
332
  def get_tracer(name: str = "mantisdk.tracing") -> trace.Tracer:
360
333
  """Get a tracer instance for creating spans.
361
334
 
@@ -0,0 +1,82 @@
1
+ # Copyright (c) Metis. All rights reserved.
2
+
3
+ """Mantisdk Semantic Conventions for Tracing.
4
+
5
+ These attributes align with Insight's primary namespace for optimal
6
+ display in the Insight UI. Insight also supports OpenInference,
7
+ Langfuse, and other SDK conventions via its attribute alias system.
8
+
9
+ See: insight/packages/shared/src/server/otel/attributeAliases.ts
10
+
11
+ Usage::
12
+
13
+ import mantisdk.tracing as tracing
14
+
15
+ with tracing.trace("my-task", input=query) as span:
16
+ span.set_attribute(tracing.semconv.USER_ID, "user-123")
17
+ span.set_attribute(tracing.semconv.SESSION_ID, "session-456")
18
+ result = do_work()
19
+ span.set_attribute(tracing.semconv.TRACE_OUTPUT, result)
20
+ """
21
+
22
+ # =============================================================================
23
+ # Trace-level attributes (for root spans)
24
+ # =============================================================================
25
+ TRACE_NAME = "insight.trace.name"
26
+ TRACE_INPUT = "insight.trace.input"
27
+ TRACE_OUTPUT = "insight.trace.output"
28
+ TRACE_METADATA = "insight.trace.metadata"
29
+ TRACE_TAGS = "insight.trace.tags"
30
+ TRACE_PUBLIC = "insight.trace.public"
31
+
32
+ # =============================================================================
33
+ # User & Session
34
+ # =============================================================================
35
+ USER_ID = "insight.user.id"
36
+ SESSION_ID = "insight.session.id"
37
+
38
+ # =============================================================================
39
+ # Environment & Version
40
+ # =============================================================================
41
+ ENVIRONMENT = "insight.environment"
42
+ RELEASE = "insight.release"
43
+ VERSION = "insight.version"
44
+
45
+ # =============================================================================
46
+ # Observation-level attributes (for child spans)
47
+ # =============================================================================
48
+ OBSERVATION_TYPE = "insight.observation.type"
49
+ OBSERVATION_INPUT = "insight.observation.input"
50
+ OBSERVATION_OUTPUT = "insight.observation.output"
51
+ OBSERVATION_METADATA = "insight.observation.metadata"
52
+ OBSERVATION_LEVEL = "insight.observation.level"
53
+ OBSERVATION_STATUS_MESSAGE = "insight.observation.status_message"
54
+
55
+ # =============================================================================
56
+ # Model & Generation attributes
57
+ # =============================================================================
58
+ MODEL_NAME = "insight.observation.model.name"
59
+ MODEL_PARAMETERS = "insight.observation.model.parameters"
60
+
61
+
62
+ # =============================================================================
63
+ # Observation types (values for OBSERVATION_TYPE)
64
+ # =============================================================================
65
+ class ObservationType:
66
+ """Valid values for the OBSERVATION_TYPE attribute."""
67
+
68
+ SPAN = "span"
69
+ GENERATION = "generation"
70
+ EVENT = "event"
71
+
72
+
73
+ # =============================================================================
74
+ # Observation levels (values for OBSERVATION_LEVEL)
75
+ # =============================================================================
76
+ class ObservationLevel:
77
+ """Valid values for the OBSERVATION_LEVEL attribute."""
78
+
79
+ DEBUG = "DEBUG"
80
+ DEFAULT = "DEFAULT"
81
+ WARNING = "WARNING"
82
+ ERROR = "ERROR"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mantisdk
3
- Version: 0.1.2
3
+ Version: 0.1.3
4
4
  Summary: Mantisdk - AI Agent Training and Evaluation Platform
5
5
  Project-URL: Homepage, https://github.com/withmetis/mantis
6
6
  Project-URL: Documentation, https://withmetis.github.io/mantis/mantisdk/
@@ -19,7 +19,6 @@ Classifier: Programming Language :: Python :: 3.11
19
19
  Classifier: Programming Language :: Python :: 3.12
20
20
  Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
21
21
  Requires-Python: >=3.10
22
- Requires-Dist: agentops>=0.4.13
23
22
  Requires-Dist: aiohttp
24
23
  Requires-Dist: aiologic
25
24
  Requires-Dist: fastapi
@@ -1,4 +1,4 @@
1
- mantisdk/__init__.py,sha256=LsOsUrIvnZ8LtDNfw5o2rCqCJn0aDJk4JIAYB1Q5HQo,718
1
+ mantisdk/__init__.py,sha256=iVsMd8gsA3K-KIIWr_GlCT-WXI-N5hYF41Ql8ukjFis,718
2
2
  mantisdk/client.py,sha256=QTH-0LDAKWLuLH7PSaZWj7XUcnbBGrJHH-w2dJiNmKM,17059
3
3
  mantisdk/config.py,sha256=9RAdsbTkSG_qnLvTwH0xTG5srLFaj1nk5Ufz1dQHGwc,14355
4
4
  mantisdk/env_var.py,sha256=OCb5CvZo5U7-HBnqC0ZmdsrS2giAh7dV85TTjz6wLqA,4372
@@ -158,10 +158,11 @@ mantisdk/tracer/base.py,sha256=icW8Xb-PFv_CJop71kGN8POujVCCZqn6K-jGja9hHlY,9454
158
158
  mantisdk/tracer/dummy.py,sha256=p-MO-sfS5t7J1Lae-ep7OW7y4rwklHUm_Jf0swM12RA,3399
159
159
  mantisdk/tracer/otel.py,sha256=-0NHS08BLFA3N2lbzecYwjz3SdCnrDS6psJaHxjBq1o,24430
160
160
  mantisdk/tracer/weave.py,sha256=UxEgESCI7bGIXhigW8YG6hCtr3ZhB86d9LOZPmFeOdc,26921
161
- mantisdk/tracing/__init__.py,sha256=8WSvcB62ogBo3oLyu6non4eoDTDh5NQyIYgbyq7ZXaI,1551
162
- mantisdk/tracing/api.py,sha256=bbBsABnfvp0B1fHbsW3pM-g2VY0AUZ2THx_tVXDLQXA,17273
161
+ mantisdk/tracing/__init__.py,sha256=_EO6OSNBcsPZ0PBKyOoq4f494_ruoGitJMnEK7iXe-o,1990
162
+ mantisdk/tracing/api.py,sha256=2p-M0oI_JSazAAeFN-Kig2lCzZ-1MIwbQvWB2Nb6stE,25741
163
163
  mantisdk/tracing/attributes.py,sha256=eCB1dmGol-OnFCOvMvVqdpgHDMNKTLIV7Y_w4ktTXxU,8617
164
- mantisdk/tracing/init.py,sha256=1AI92hS8HY96pfiApczb4_Ciu1g8YHwe2P8e-FLo3tQ,12472
164
+ mantisdk/tracing/init.py,sha256=8RYpAv_gz2gfvkJuI_1SlomG2fzr7ReIZhjtdBzdLNk,11369
165
+ mantisdk/tracing/semconv.py,sha256=3aulZ5Mlk1kJY1XdHXH1SJmr4g4Ut-1hij6gedshrm8,3205
165
166
  mantisdk/tracing/exporters/__init__.py,sha256=Y2cnRuApIc34dJpoJGLakZfrzyzyFrr0dchHuTiDpmw,191
166
167
  mantisdk/tracing/exporters/insight.py,sha256=kVq7syVpT06nD6Lu8-tjthnIqALuBGkFb6ICOAajLy8,6753
167
168
  mantisdk/tracing/instrumentors/__init__.py,sha256=NXwK6SYJgrEg9zQM8uvthL43a2lyfRgx0gYAzcEnFNg,392
@@ -193,8 +194,8 @@ mantisdk/verl/daemon.py,sha256=cvIGDkotN6MPp-DubCeKBfD9hSoZCgRyIACI9X7D7uw,54493
193
194
  mantisdk/verl/dataset.py,sha256=Hr0K9oXuj7q8pf08BuvNRTbIgyNo0XY_N_JVA5jHUvI,1175
194
195
  mantisdk/verl/entrypoint.py,sha256=dnZ7TwCe9hC1kRXm_ypRTrSR9cPXz3LcxXYjtPVuOHs,8627
195
196
  mantisdk/verl/trainer.py,sha256=TCaVXo65iNcEEGujuIbx2yQ_cMfBYyU5Uudx9gOBSNI,25447
196
- mantisdk-0.1.2.dist-info/METADATA,sha256=P2Skwi3Cf5XLGN0un6XEgc5NHgKi-fvNTZ3V9f99VpE,3418
197
- mantisdk-0.1.2.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
198
- mantisdk-0.1.2.dist-info/entry_points.txt,sha256=yDYe8wx2pXbBXBaRPtRwt6OL01VPHf6GiFsfauISW3M,42
199
- mantisdk-0.1.2.dist-info/licenses/LICENSE,sha256=j3Flk3DFJo2aHclipGIyVA6PymNGJYbY76qVqrSSogg,1046
200
- mantisdk-0.1.2.dist-info/RECORD,,
197
+ mantisdk-0.1.3.dist-info/METADATA,sha256=eaJbnQsPVqpKZXwfkBwqCGFYPWf7TlSm9sUVpPglD8c,3386
198
+ mantisdk-0.1.3.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
199
+ mantisdk-0.1.3.dist-info/entry_points.txt,sha256=yDYe8wx2pXbBXBaRPtRwt6OL01VPHf6GiFsfauISW3M,42
200
+ mantisdk-0.1.3.dist-info/licenses/LICENSE,sha256=j3Flk3DFJo2aHclipGIyVA6PymNGJYbY76qVqrSSogg,1046
201
+ mantisdk-0.1.3.dist-info/RECORD,,