fiddler-otel 0.1.1__tar.gz

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.
@@ -0,0 +1,170 @@
1
+ Metadata-Version: 2.4
2
+ Name: fiddler-otel
3
+ Version: 0.1.1
4
+ Summary: Core OpenTelemetry instrumentation library for Fiddler GenAI observability
5
+ Author-email: Fiddler AI <support@fiddler.ai>
6
+ License-Expression: Apache-2.0
7
+ Project-URL: Homepage, https://fiddler.ai
8
+ Project-URL: Documentation, https://docs.fiddler.ai
9
+ Project-URL: Repository, https://github.com/fiddler-labs/fiddler-sdk
10
+ Project-URL: Issues, https://github.com/fiddler-labs/fiddler-sdk/issues
11
+ Keywords: fiddler,ai,genai,llm,monitoring,observability,instrumentation,opentelemetry
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
15
+ Classifier: Topic :: System :: Monitoring
16
+ Classifier: Topic :: Software Development :: Quality Assurance
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Operating System :: OS Independent
23
+ Requires-Python: >=3.10
24
+ Description-Content-Type: text/markdown
25
+ Requires-Dist: opentelemetry-api>=1.27.0
26
+ Requires-Dist: opentelemetry-sdk>=1.27.0
27
+ Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.27.0
28
+ Requires-Dist: pydantic>=2.0
29
+
30
+ # fiddler-otel
31
+
32
+ Core OpenTelemetry instrumentation library for **Fiddler GenAI observability**. This is the foundation package used by all Fiddler framework integrations (`fiddler-langgraph`, `fiddler-langchain`).
33
+
34
+ ## Installation
35
+
36
+ ```bash
37
+ pip install fiddler-otel
38
+ ```
39
+
40
+ ## Quick Start
41
+
42
+ ### Using the `@trace` decorator
43
+
44
+ The simplest way to instrument any Python function — synchronous or async:
45
+
46
+ ```python
47
+ from fiddler_otel import FiddlerClient, trace
48
+
49
+ client = FiddlerClient(
50
+ api_key="YOUR_API_KEY",
51
+ application_id="YOUR_APPLICATION_ID",
52
+ url="https://your-instance.fiddler.ai",
53
+ )
54
+
55
+ @trace(span_type="generation", name="my_llm_call")
56
+ def call_llm(prompt: str) -> str:
57
+ # your LLM call here
58
+ return response
59
+
60
+ @trace(span_type="chain")
61
+ async def run_pipeline(user_input: str) -> str:
62
+ result = call_llm(user_input)
63
+ return result
64
+ ```
65
+
66
+ ### Using span wrappers manually
67
+
68
+ For fine-grained control over span attributes:
69
+
70
+ ```python
71
+ from fiddler_otel import FiddlerClient, FiddlerGeneration, FiddlerChain, FiddlerTool
72
+
73
+ client = FiddlerClient(
74
+ api_key="YOUR_API_KEY",
75
+ application_id="YOUR_APPLICATION_ID",
76
+ url="https://your-instance.fiddler.ai",
77
+ )
78
+
79
+ with client.start_span("my_agent", span_type="chain") as chain_span:
80
+ gen = FiddlerGeneration(client.start_span("llm_call"))
81
+ with gen as span:
82
+ span.set_input("What is the capital of France?")
83
+ response = call_llm("What is the capital of France?")
84
+ span.set_output(response)
85
+ span.set_usage(input_tokens=10, output_tokens=5, total_tokens=15)
86
+ ```
87
+
88
+ ### Multi-turn Conversations
89
+
90
+ Link multiple agent invocations into a single conversation:
91
+
92
+ ```python
93
+ from fiddler_otel import set_conversation_id
94
+ import uuid
95
+
96
+ set_conversation_id(str(uuid.uuid4()))
97
+
98
+ # All spans created after this call carry the same conversation_id
99
+ result = my_agent(user_message)
100
+ ```
101
+
102
+ ### Local JSONL Capture
103
+
104
+ Capture all spans to a local file for debugging without sending to Fiddler:
105
+
106
+ ```python
107
+ client = FiddlerClient(
108
+ api_key="...",
109
+ application_id="...",
110
+ url="...",
111
+ jsonl_capture_enabled=True,
112
+ jsonl_file_path="trace_data.jsonl",
113
+ )
114
+ ```
115
+
116
+ Or via environment variables:
117
+
118
+ ```bash
119
+ FIDDLER_JSONL_ENABLED=true \
120
+ FIDDLER_JSONL_FILE=trace_data.jsonl \
121
+ python my_agent.py
122
+ ```
123
+
124
+ ### Console Tracing (Development)
125
+
126
+ Print all spans to stdout during development:
127
+
128
+ ```python
129
+ client = FiddlerClient(
130
+ api_key="...",
131
+ application_id="...",
132
+ url="...",
133
+ console_tracer=True,
134
+ )
135
+ ```
136
+
137
+ ## Public API
138
+
139
+ | Symbol | Description |
140
+ |---|---|
141
+ | `FiddlerClient` | Main client — configures the tracer and exports spans to Fiddler |
142
+ | `FiddlerSpan` | Base span wrapper with `set_input`, `set_output`, `set_attribute` |
143
+ | `FiddlerGeneration` | LLM span wrapper — adds `set_usage`, `set_messages`, `set_context` |
144
+ | `FiddlerChain` | Chain/pipeline span wrapper |
145
+ | `FiddlerTool` | Tool call span wrapper |
146
+ | `trace` | Decorator for automatic span creation around any function |
147
+ | `get_current_span` | Get the active Fiddler span inside a traced function |
148
+ | `set_conversation_id` | Link multiple invocations into one conversation |
149
+ | `get_client` | Return the global singleton `FiddlerClient` |
150
+
151
+ ## Context Isolation
152
+
153
+ `fiddler-otel` uses its own **isolated OpenTelemetry context** that does not interfere with any existing global tracer in your application. If you already use OpenTelemetry for infrastructure tracing, Fiddler spans will not appear in your infrastructure traces and vice versa.
154
+
155
+ ## Framework Integrations
156
+
157
+ | Package | Framework | Install |
158
+ |---|---|---|
159
+ | `fiddler-langgraph` | LangGraph + LangChain v0.x | `pip install fiddler-langgraph` |
160
+ | `fiddler-langchain` | LangChain V1 (`create_agent`) | `pip install fiddler-langchain` |
161
+
162
+ Both integration packages depend on `fiddler-otel` and re-export its core symbols, so you typically only need to install the integration package for your framework.
163
+
164
+ ## Requirements
165
+
166
+ - Python 3.10+
167
+ - `opentelemetry-api >= 1.27.0`
168
+ - `opentelemetry-sdk >= 1.27.0`
169
+ - `opentelemetry-exporter-otlp-proto-http >= 1.27.0`
170
+ - `pydantic >= 2.0`
@@ -0,0 +1,141 @@
1
+ # fiddler-otel
2
+
3
+ Core OpenTelemetry instrumentation library for **Fiddler GenAI observability**. This is the foundation package used by all Fiddler framework integrations (`fiddler-langgraph`, `fiddler-langchain`).
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pip install fiddler-otel
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ### Using the `@trace` decorator
14
+
15
+ The simplest way to instrument any Python function — synchronous or async:
16
+
17
+ ```python
18
+ from fiddler_otel import FiddlerClient, trace
19
+
20
+ client = FiddlerClient(
21
+ api_key="YOUR_API_KEY",
22
+ application_id="YOUR_APPLICATION_ID",
23
+ url="https://your-instance.fiddler.ai",
24
+ )
25
+
26
+ @trace(span_type="generation", name="my_llm_call")
27
+ def call_llm(prompt: str) -> str:
28
+ # your LLM call here
29
+ return response
30
+
31
+ @trace(span_type="chain")
32
+ async def run_pipeline(user_input: str) -> str:
33
+ result = call_llm(user_input)
34
+ return result
35
+ ```
36
+
37
+ ### Using span wrappers manually
38
+
39
+ For fine-grained control over span attributes:
40
+
41
+ ```python
42
+ from fiddler_otel import FiddlerClient, FiddlerGeneration, FiddlerChain, FiddlerTool
43
+
44
+ client = FiddlerClient(
45
+ api_key="YOUR_API_KEY",
46
+ application_id="YOUR_APPLICATION_ID",
47
+ url="https://your-instance.fiddler.ai",
48
+ )
49
+
50
+ with client.start_span("my_agent", span_type="chain") as chain_span:
51
+ gen = FiddlerGeneration(client.start_span("llm_call"))
52
+ with gen as span:
53
+ span.set_input("What is the capital of France?")
54
+ response = call_llm("What is the capital of France?")
55
+ span.set_output(response)
56
+ span.set_usage(input_tokens=10, output_tokens=5, total_tokens=15)
57
+ ```
58
+
59
+ ### Multi-turn Conversations
60
+
61
+ Link multiple agent invocations into a single conversation:
62
+
63
+ ```python
64
+ from fiddler_otel import set_conversation_id
65
+ import uuid
66
+
67
+ set_conversation_id(str(uuid.uuid4()))
68
+
69
+ # All spans created after this call carry the same conversation_id
70
+ result = my_agent(user_message)
71
+ ```
72
+
73
+ ### Local JSONL Capture
74
+
75
+ Capture all spans to a local file for debugging without sending to Fiddler:
76
+
77
+ ```python
78
+ client = FiddlerClient(
79
+ api_key="...",
80
+ application_id="...",
81
+ url="...",
82
+ jsonl_capture_enabled=True,
83
+ jsonl_file_path="trace_data.jsonl",
84
+ )
85
+ ```
86
+
87
+ Or via environment variables:
88
+
89
+ ```bash
90
+ FIDDLER_JSONL_ENABLED=true \
91
+ FIDDLER_JSONL_FILE=trace_data.jsonl \
92
+ python my_agent.py
93
+ ```
94
+
95
+ ### Console Tracing (Development)
96
+
97
+ Print all spans to stdout during development:
98
+
99
+ ```python
100
+ client = FiddlerClient(
101
+ api_key="...",
102
+ application_id="...",
103
+ url="...",
104
+ console_tracer=True,
105
+ )
106
+ ```
107
+
108
+ ## Public API
109
+
110
+ | Symbol | Description |
111
+ |---|---|
112
+ | `FiddlerClient` | Main client — configures the tracer and exports spans to Fiddler |
113
+ | `FiddlerSpan` | Base span wrapper with `set_input`, `set_output`, `set_attribute` |
114
+ | `FiddlerGeneration` | LLM span wrapper — adds `set_usage`, `set_messages`, `set_context` |
115
+ | `FiddlerChain` | Chain/pipeline span wrapper |
116
+ | `FiddlerTool` | Tool call span wrapper |
117
+ | `trace` | Decorator for automatic span creation around any function |
118
+ | `get_current_span` | Get the active Fiddler span inside a traced function |
119
+ | `set_conversation_id` | Link multiple invocations into one conversation |
120
+ | `get_client` | Return the global singleton `FiddlerClient` |
121
+
122
+ ## Context Isolation
123
+
124
+ `fiddler-otel` uses its own **isolated OpenTelemetry context** that does not interfere with any existing global tracer in your application. If you already use OpenTelemetry for infrastructure tracing, Fiddler spans will not appear in your infrastructure traces and vice versa.
125
+
126
+ ## Framework Integrations
127
+
128
+ | Package | Framework | Install |
129
+ |---|---|---|
130
+ | `fiddler-langgraph` | LangGraph + LangChain v0.x | `pip install fiddler-langgraph` |
131
+ | `fiddler-langchain` | LangChain V1 (`create_agent`) | `pip install fiddler-langchain` |
132
+
133
+ Both integration packages depend on `fiddler-otel` and re-export its core symbols, so you typically only need to install the integration package for your framework.
134
+
135
+ ## Requirements
136
+
137
+ - Python 3.10+
138
+ - `opentelemetry-api >= 1.27.0`
139
+ - `opentelemetry-sdk >= 1.27.0`
140
+ - `opentelemetry-exporter-otlp-proto-http >= 1.27.0`
141
+ - `pydantic >= 2.0`
@@ -0,0 +1 @@
1
+ 0.1.1
@@ -0,0 +1,49 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0,<82.0.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "fiddler-otel"
7
+ dynamic = ["version"]
8
+ authors = [
9
+ {name = "Fiddler AI", email = "support@fiddler.ai"},
10
+ ]
11
+ description = "Core OpenTelemetry instrumentation library for Fiddler GenAI observability"
12
+ readme = "README.md"
13
+ license = "Apache-2.0"
14
+ requires-python = ">=3.10"
15
+ classifiers = [
16
+ "Development Status :: 3 - Alpha",
17
+ "Intended Audience :: Developers",
18
+ "Topic :: Software Development :: Libraries :: Python Modules",
19
+ "Topic :: System :: Monitoring",
20
+ "Topic :: Software Development :: Quality Assurance",
21
+ "Programming Language :: Python :: 3",
22
+ "Programming Language :: Python :: 3.10",
23
+ "Programming Language :: Python :: 3.11",
24
+ "Programming Language :: Python :: 3.12",
25
+ "Programming Language :: Python :: 3.13",
26
+ "Operating System :: OS Independent",
27
+ ]
28
+ keywords = ["fiddler", "ai", "genai", "llm", "monitoring", "observability", "instrumentation", "opentelemetry"]
29
+ dependencies = [
30
+ "opentelemetry-api>=1.27.0",
31
+ "opentelemetry-sdk>=1.27.0",
32
+ "opentelemetry-exporter-otlp-proto-http>=1.27.0",
33
+ "pydantic>=2.0",
34
+ ]
35
+
36
+ [project.urls]
37
+ Homepage = "https://fiddler.ai"
38
+ Documentation = "https://docs.fiddler.ai"
39
+ Repository = "https://github.com/fiddler-labs/fiddler-sdk"
40
+ Issues = "https://github.com/fiddler-labs/fiddler-sdk/issues"
41
+
42
+ [tool.setuptools.packages.find]
43
+ where = ["src"]
44
+
45
+ [tool.setuptools.dynamic]
46
+ version = {file = ["VERSION"]}
47
+
48
+ [tool.setuptools.package-data]
49
+ fiddler_otel = ["VERSION"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,26 @@
1
+ """Fiddler OTel - core OpenTelemetry instrumentation for GenAI applications."""
2
+
3
+ from importlib.metadata import PackageNotFoundError, version
4
+
5
+ from fiddler_otel.attributes import set_conversation_id
6
+ from fiddler_otel.client import FiddlerClient, get_client
7
+ from fiddler_otel.decorators import get_current_span, trace
8
+ from fiddler_otel.span_wrapper import FiddlerChain, FiddlerGeneration, FiddlerSpan, FiddlerTool
9
+
10
+ try:
11
+ __version__ = version('fiddler-otel')
12
+ except PackageNotFoundError:
13
+ __version__ = 'unknown'
14
+
15
+ __all__ = [
16
+ 'FiddlerChain',
17
+ 'FiddlerClient',
18
+ 'FiddlerGeneration',
19
+ 'FiddlerSpan',
20
+ 'FiddlerTool',
21
+ '__version__',
22
+ 'get_client',
23
+ 'get_current_span',
24
+ 'set_conversation_id',
25
+ 'trace',
26
+ ]
@@ -0,0 +1,97 @@
1
+ """OpenTelemetry span attributes for Fiddler instrumentation."""
2
+
3
+ import contextvars
4
+ from typing import Any
5
+
6
+ from pydantic import ConfigDict, validate_call
7
+
8
+ # Key used for storing Fiddler-specific attributes in metadata dictionary
9
+ FIDDLER_METADATA_KEY = '_fiddler_attributes'
10
+
11
+ # Template strings for OpenTelemetry attribute key formatting
12
+ FIDDLER_USER_SPAN_ATTRIBUTE_TEMPLATE = 'fiddler.span.user.{key}'
13
+ FIDDLER_USER_SESSION_ATTRIBUTE_TEMPLATE = 'fiddler.session.user.{key}'
14
+
15
+
16
+ class FiddlerSpanAttributes: # pylint: disable=too-few-public-methods
17
+ """Constants for Fiddler OpenTelemetry span attributes."""
18
+
19
+ # common attributes
20
+ AGENT_NAME = 'gen_ai.agent.name'
21
+ AGENT_ID = 'gen_ai.agent.id'
22
+ CONVERSATION_ID = 'gen_ai.conversation.id'
23
+ TYPE = 'fiddler.span.type'
24
+ SERVICE_VERSION = 'service.version'
25
+
26
+ # LLM attributes
27
+ LLM_INPUT_SYSTEM = 'gen_ai.llm.input.system'
28
+ LLM_INPUT_USER = 'gen_ai.llm.input.user'
29
+ LLM_OUTPUT = 'gen_ai.llm.output'
30
+ LLM_CONTEXT = 'gen_ai.llm.context'
31
+
32
+ # Model attributes - following OpenTelemetry semantic conventions
33
+ LLM_REQUEST_MODEL = 'gen_ai.request.model'
34
+ LLM_SYSTEM = 'gen_ai.system'
35
+
36
+ # Token usage attributes
37
+ LLM_TOKEN_COUNT_INPUT = 'gen_ai.usage.input_tokens'
38
+ LLM_TOKEN_COUNT_OUTPUT = 'gen_ai.usage.output_tokens'
39
+ LLM_TOKEN_COUNT_TOTAL = 'gen_ai.usage.total_tokens'
40
+ GEN_AI_INPUT_MESSAGES = 'gen_ai.input.messages'
41
+ GEN_AI_OUTPUT_MESSAGES = 'gen_ai.output.messages'
42
+
43
+ # tool attributes
44
+ TOOL_INPUT = 'gen_ai.tool.input'
45
+ TOOL_OUTPUT = 'gen_ai.tool.output'
46
+ TOOL_NAME = 'gen_ai.tool.name'
47
+ TOOL_DEFINITIONS = 'gen_ai.tool.definitions'
48
+
49
+
50
+ class FiddlerResourceAttributes:
51
+ """Constants for Fiddler OpenTelemetry resource attributes."""
52
+
53
+ APPLICATION_ID = 'application.id'
54
+
55
+
56
+ class SpanType:
57
+ """Constants for Fiddler OpenTelemetry span types."""
58
+
59
+ AGENT = 'agent'
60
+ CHAIN = 'chain'
61
+ TOOL = 'tool'
62
+ LLM = 'llm'
63
+ OTHER = 'other'
64
+
65
+
66
+ # context variable for conversation ID - used to store the conversation ID for the current
67
+ # thread/async coroutine. Note that contextvars are shallow copied; dictionaries/lists are not
68
+ # copied deeply and are shared between threads/coroutines.
69
+ _CONVERSATION_ID: contextvars.ContextVar[str] = contextvars.ContextVar(
70
+ '_CONVERSATION_ID', default=''
71
+ )
72
+ _CUSTOM_ATTRIBUTES: contextvars.ContextVar[dict[str, Any] | None] = contextvars.ContextVar(
73
+ '_CUSTOM_ATTRIBUTES', default=None
74
+ )
75
+
76
+
77
+ @validate_call(config=ConfigDict(strict=True))
78
+ def set_conversation_id(conversation_id: str) -> None:
79
+ """Set the conversation ID for the current execution context.
80
+
81
+ The conversation ID is propagated to all spans created in the current
82
+ thread or async coroutine, allowing the Fiddler dashboard to filter and
83
+ display the full ordered sequence of operations for a single conversation.
84
+
85
+ This value persists until it is called again with a new ID.
86
+
87
+ :param conversation_id: Unique identifier for the conversation session.
88
+
89
+ Example::
90
+
91
+ from fiddler_otel import set_conversation_id
92
+ import uuid
93
+
94
+ set_conversation_id(str(uuid.uuid4()))
95
+ agent.invoke({"messages": [{"role": "user", "content": "Hello"}]})
96
+ """
97
+ _CONVERSATION_ID.set(conversation_id)