threadify-sdk 0.2.6__tar.gz → 0.2.8__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.
- {threadify_sdk-0.2.6/threadify_sdk.egg-info → threadify_sdk-0.2.8}/PKG-INFO +33 -1
- {threadify_sdk-0.2.6 → threadify_sdk-0.2.8}/README.md +32 -0
- {threadify_sdk-0.2.6 → threadify_sdk-0.2.8}/pyproject.toml +1 -1
- {threadify_sdk-0.2.6 → threadify_sdk-0.2.8}/threadify/connection.py +13 -0
- {threadify_sdk-0.2.6 → threadify_sdk-0.2.8}/threadify/models.py +1 -0
- {threadify_sdk-0.2.6 → threadify_sdk-0.2.8}/threadify/otel_exporter.py +17 -0
- {threadify_sdk-0.2.6 → threadify_sdk-0.2.8}/threadify/thread.py +4 -0
- {threadify_sdk-0.2.6 → threadify_sdk-0.2.8/threadify_sdk.egg-info}/PKG-INFO +33 -1
- {threadify_sdk-0.2.6 → threadify_sdk-0.2.8}/CHANGELOG.md +0 -0
- {threadify_sdk-0.2.6 → threadify_sdk-0.2.8}/LICENSE +0 -0
- {threadify_sdk-0.2.6 → threadify_sdk-0.2.8}/MANIFEST.in +0 -0
- {threadify_sdk-0.2.6 → threadify_sdk-0.2.8}/setup.cfg +0 -0
- {threadify_sdk-0.2.6 → threadify_sdk-0.2.8}/tests/test_client.py +0 -0
- {threadify_sdk-0.2.6 → threadify_sdk-0.2.8}/tests/test_connection.py +0 -0
- {threadify_sdk-0.2.6 → threadify_sdk-0.2.8}/tests/test_data_retriever.py +0 -0
- {threadify_sdk-0.2.6 → threadify_sdk-0.2.8}/tests/test_models.py +0 -0
- {threadify_sdk-0.2.6 → threadify_sdk-0.2.8}/tests/test_notification.py +0 -0
- {threadify_sdk-0.2.6 → threadify_sdk-0.2.8}/tests/test_step.py +0 -0
- {threadify_sdk-0.2.6 → threadify_sdk-0.2.8}/tests/test_thread.py +0 -0
- {threadify_sdk-0.2.6 → threadify_sdk-0.2.8}/threadify/__init__.py +0 -0
- {threadify_sdk-0.2.6 → threadify_sdk-0.2.8}/threadify/client.py +0 -0
- {threadify_sdk-0.2.6 → threadify_sdk-0.2.8}/threadify/data_retriever.py +0 -0
- {threadify_sdk-0.2.6 → threadify_sdk-0.2.8}/threadify/notification.py +0 -0
- {threadify_sdk-0.2.6 → threadify_sdk-0.2.8}/threadify/step.py +0 -0
- {threadify_sdk-0.2.6 → threadify_sdk-0.2.8}/threadify_sdk.egg-info/SOURCES.txt +0 -0
- {threadify_sdk-0.2.6 → threadify_sdk-0.2.8}/threadify_sdk.egg-info/dependency_links.txt +0 -0
- {threadify_sdk-0.2.6 → threadify_sdk-0.2.8}/threadify_sdk.egg-info/requires.txt +0 -0
- {threadify_sdk-0.2.6 → threadify_sdk-0.2.8}/threadify_sdk.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: threadify-sdk
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.8
|
|
4
4
|
Summary: Python SDK for Threadify — Service-delivery intelligence. Track every customer request from start to finish across every system, team, and partner. Visit: https://threadify.dev
|
|
5
5
|
Author-email: Threadify Team <team@threadify.dev>
|
|
6
6
|
License: MIT
|
|
@@ -167,6 +167,38 @@ This SDK follows [Semantic Versioning](https://semver.org/) and [Conventional Co
|
|
|
167
167
|
- `feat: ...` -> Minor bump
|
|
168
168
|
- `feat!: ...` or `BREAKING CHANGE: ...` -> Major bump
|
|
169
169
|
|
|
170
|
+
## OpenTelemetry Integration
|
|
171
|
+
|
|
172
|
+
The Python SDK includes the OpenTelemetry SpanExporter in the core package.
|
|
173
|
+
|
|
174
|
+
```python
|
|
175
|
+
from opentelemetry import trace
|
|
176
|
+
from opentelemetry.sdk.trace import TracerProvider
|
|
177
|
+
from opentelemetry.sdk.trace.export import BatchSpanProcessor
|
|
178
|
+
from threadify import Threadify
|
|
179
|
+
|
|
180
|
+
conn = await Threadify.connect("api-key", service_name="checkout-service")
|
|
181
|
+
|
|
182
|
+
# Create exporter
|
|
183
|
+
exporter = conn.create_span_exporter(options={"refs": ["order.id", "customer.id"]})
|
|
184
|
+
|
|
185
|
+
# Filter spans by name — exact match or prefix wildcard with *
|
|
186
|
+
exporter = conn.create_span_exporter(options={
|
|
187
|
+
"refs": ["order.id", "customer.id"],
|
|
188
|
+
"filters": ["invoke_llm", "adk.before*", "llm.*"],
|
|
189
|
+
})
|
|
190
|
+
|
|
191
|
+
provider = TracerProvider()
|
|
192
|
+
provider.add_span_processor(BatchSpanProcessor(exporter))
|
|
193
|
+
trace.set_tracer_provider(provider)
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
**Filter patterns:**
|
|
197
|
+
|
|
198
|
+
- `"invoke_llm"` — exact match
|
|
199
|
+
- `"adk.before*"` — prefix wildcard, drops any span starting with `adk.before`
|
|
200
|
+
- `"llm.*"` — prefix wildcard, drops any span starting with `llm.`
|
|
201
|
+
|
|
170
202
|
## Testing
|
|
171
203
|
|
|
172
204
|
To run the SDK tests, execute:
|
|
@@ -140,6 +140,38 @@ This SDK follows [Semantic Versioning](https://semver.org/) and [Conventional Co
|
|
|
140
140
|
- `feat: ...` -> Minor bump
|
|
141
141
|
- `feat!: ...` or `BREAKING CHANGE: ...` -> Major bump
|
|
142
142
|
|
|
143
|
+
## OpenTelemetry Integration
|
|
144
|
+
|
|
145
|
+
The Python SDK includes the OpenTelemetry SpanExporter in the core package.
|
|
146
|
+
|
|
147
|
+
```python
|
|
148
|
+
from opentelemetry import trace
|
|
149
|
+
from opentelemetry.sdk.trace import TracerProvider
|
|
150
|
+
from opentelemetry.sdk.trace.export import BatchSpanProcessor
|
|
151
|
+
from threadify import Threadify
|
|
152
|
+
|
|
153
|
+
conn = await Threadify.connect("api-key", service_name="checkout-service")
|
|
154
|
+
|
|
155
|
+
# Create exporter
|
|
156
|
+
exporter = conn.create_span_exporter(options={"refs": ["order.id", "customer.id"]})
|
|
157
|
+
|
|
158
|
+
# Filter spans by name — exact match or prefix wildcard with *
|
|
159
|
+
exporter = conn.create_span_exporter(options={
|
|
160
|
+
"refs": ["order.id", "customer.id"],
|
|
161
|
+
"filters": ["invoke_llm", "adk.before*", "llm.*"],
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
provider = TracerProvider()
|
|
165
|
+
provider.add_span_processor(BatchSpanProcessor(exporter))
|
|
166
|
+
trace.set_tracer_provider(provider)
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
**Filter patterns:**
|
|
170
|
+
|
|
171
|
+
- `"invoke_llm"` — exact match
|
|
172
|
+
- `"adk.before*"` — prefix wildcard, drops any span starting with `adk.before`
|
|
173
|
+
- `"llm.*"` — prefix wildcard, drops any span starting with `llm.`
|
|
174
|
+
|
|
143
175
|
## Testing
|
|
144
176
|
|
|
145
177
|
To run the SDK tests, execute:
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "threadify-sdk"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.8"
|
|
8
8
|
description = "Python SDK for Threadify — Service-delivery intelligence. Track every customer request from start to finish across every system, team, and partner. Visit: https://threadify.dev"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -35,6 +35,7 @@ from threadify.models import (
|
|
|
35
35
|
FIELD_SERVICE_NAME,
|
|
36
36
|
FIELD_STATUS,
|
|
37
37
|
FIELD_STEP_NAME,
|
|
38
|
+
FIELD_TAGS,
|
|
38
39
|
FIELD_THREAD_ID,
|
|
39
40
|
FIELD_THREAD_ID_ACK,
|
|
40
41
|
FIELD_THREAD_TOKEN,
|
|
@@ -144,6 +145,7 @@ class Connection:
|
|
|
144
145
|
contract_name: str = "",
|
|
145
146
|
service_name: str = "",
|
|
146
147
|
refs: dict[str, Any] | None = None,
|
|
148
|
+
tags: list[str] | None = None,
|
|
147
149
|
) -> ThreadInstance:
|
|
148
150
|
from threadify.thread import ThreadInstance
|
|
149
151
|
|
|
@@ -174,6 +176,13 @@ class Connection:
|
|
|
174
176
|
|
|
175
177
|
msg[FIELD_ROLE] = role
|
|
176
178
|
|
|
179
|
+
# Validate and attach tags if provided
|
|
180
|
+
if tags:
|
|
181
|
+
for t in tags:
|
|
182
|
+
if not isinstance(t, str) or not t.strip():
|
|
183
|
+
raise ValueError("Each tag must be a non-empty string")
|
|
184
|
+
msg[FIELD_TAGS] = list(tags)
|
|
185
|
+
|
|
177
186
|
await self._send(msg)
|
|
178
187
|
|
|
179
188
|
resp = await self._wait_response(lambda m: m.get(FIELD_ACTION) == ACTION_START_THREAD)
|
|
@@ -183,6 +192,7 @@ class Connection:
|
|
|
183
192
|
|
|
184
193
|
thread_id = resp[FIELD_THREAD_ID]
|
|
185
194
|
thread = ThreadInstance(self, thread_id, contract_name, "", resp.get(FIELD_ACCESS_LEVEL, ""), None)
|
|
195
|
+
thread.tags = list(tags) if tags else []
|
|
186
196
|
self._threads[thread_id] = thread
|
|
187
197
|
self._logger.debug(f"Thread started: {thread_id}")
|
|
188
198
|
return thread
|
|
@@ -464,6 +474,9 @@ class Connection:
|
|
|
464
474
|
Args:
|
|
465
475
|
options: Optional configuration dict. Supported keys:
|
|
466
476
|
- ``refs``: list of attribute keys to map to Threadify refs.
|
|
477
|
+
- ``filters``: list of span-name patterns to drop. A trailing ``*``
|
|
478
|
+
acts as a wildcard prefix match; otherwise an exact match is used.
|
|
479
|
+
Example: ``["invoke_llm", "adk.before*", "llm.*"]``.
|
|
467
480
|
|
|
468
481
|
Returns:
|
|
469
482
|
A :class:`~threadify.otel_exporter.ThreadifySpanExporter` instance.
|
|
@@ -73,6 +73,9 @@ class ThreadifySpanExporter(_SpanExporterBase):
|
|
|
73
73
|
else:
|
|
74
74
|
self._refs_map = {}
|
|
75
75
|
|
|
76
|
+
# Span-name filters; e.g. ["invoke_llm", "adk.before*", "llm.*"]
|
|
77
|
+
self._filters: list[str] = self._options.get("filters", [])
|
|
78
|
+
|
|
76
79
|
# trace_id -> asyncio.Future[ThreadInstance]
|
|
77
80
|
self._trace_threads: dict[str, asyncio.Future[Any]] = {}
|
|
78
81
|
|
|
@@ -111,6 +114,8 @@ class ThreadifySpanExporter(_SpanExporterBase):
|
|
|
111
114
|
|
|
112
115
|
async def _process_all(self, spans: list[ReadableSpan]) -> None:
|
|
113
116
|
for span in spans:
|
|
117
|
+
if self._should_drop(span.name):
|
|
118
|
+
continue
|
|
114
119
|
await self._process_span(span)
|
|
115
120
|
|
|
116
121
|
async def _process_span(self, span: ReadableSpan) -> None:
|
|
@@ -276,6 +281,18 @@ class ThreadifySpanExporter(_SpanExporterBase):
|
|
|
276
281
|
|
|
277
282
|
return await self._trace_threads[trace_id]
|
|
278
283
|
|
|
284
|
+
def _should_drop(self, name: str) -> bool:
|
|
285
|
+
for f in self._filters:
|
|
286
|
+
if not f:
|
|
287
|
+
continue
|
|
288
|
+
if f.endswith("*"):
|
|
289
|
+
if name.startswith(f[:-1]):
|
|
290
|
+
return True
|
|
291
|
+
continue
|
|
292
|
+
if name == f:
|
|
293
|
+
return True
|
|
294
|
+
return False
|
|
295
|
+
|
|
279
296
|
@staticmethod
|
|
280
297
|
def _span_attr(span: ReadableSpan, key: str) -> str | None:
|
|
281
298
|
value = span.attributes.get(key)
|
|
@@ -71,6 +71,7 @@ class ThreadInstance:
|
|
|
71
71
|
self.role = role
|
|
72
72
|
self.access_level = access_level
|
|
73
73
|
self.refs: dict[str, str] = refs or {}
|
|
74
|
+
self.tags: list[str] = [] # Tags applied at thread creation (immutable)
|
|
74
75
|
|
|
75
76
|
self._steps: dict[str, Any] = {}
|
|
76
77
|
self._pending_waits: dict[str, _PendingWait] = {}
|
|
@@ -300,6 +301,9 @@ class ThreadInstance:
|
|
|
300
301
|
Args:
|
|
301
302
|
options: Optional configuration dict. Supported keys:
|
|
302
303
|
- ``refs``: list of attribute keys to map to Threadify refs.
|
|
304
|
+
- ``filters``: list of span-name patterns to drop. A trailing ``*``
|
|
305
|
+
acts as a wildcard prefix match; otherwise an exact match is used.
|
|
306
|
+
Example: ``["invoke_llm", "adk.before*", "llm.*"]``.
|
|
303
307
|
|
|
304
308
|
Returns:
|
|
305
309
|
A :class:`~threadify.otel_exporter.ThreadifySpanExporter` instance.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: threadify-sdk
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.8
|
|
4
4
|
Summary: Python SDK for Threadify — Service-delivery intelligence. Track every customer request from start to finish across every system, team, and partner. Visit: https://threadify.dev
|
|
5
5
|
Author-email: Threadify Team <team@threadify.dev>
|
|
6
6
|
License: MIT
|
|
@@ -167,6 +167,38 @@ This SDK follows [Semantic Versioning](https://semver.org/) and [Conventional Co
|
|
|
167
167
|
- `feat: ...` -> Minor bump
|
|
168
168
|
- `feat!: ...` or `BREAKING CHANGE: ...` -> Major bump
|
|
169
169
|
|
|
170
|
+
## OpenTelemetry Integration
|
|
171
|
+
|
|
172
|
+
The Python SDK includes the OpenTelemetry SpanExporter in the core package.
|
|
173
|
+
|
|
174
|
+
```python
|
|
175
|
+
from opentelemetry import trace
|
|
176
|
+
from opentelemetry.sdk.trace import TracerProvider
|
|
177
|
+
from opentelemetry.sdk.trace.export import BatchSpanProcessor
|
|
178
|
+
from threadify import Threadify
|
|
179
|
+
|
|
180
|
+
conn = await Threadify.connect("api-key", service_name="checkout-service")
|
|
181
|
+
|
|
182
|
+
# Create exporter
|
|
183
|
+
exporter = conn.create_span_exporter(options={"refs": ["order.id", "customer.id"]})
|
|
184
|
+
|
|
185
|
+
# Filter spans by name — exact match or prefix wildcard with *
|
|
186
|
+
exporter = conn.create_span_exporter(options={
|
|
187
|
+
"refs": ["order.id", "customer.id"],
|
|
188
|
+
"filters": ["invoke_llm", "adk.before*", "llm.*"],
|
|
189
|
+
})
|
|
190
|
+
|
|
191
|
+
provider = TracerProvider()
|
|
192
|
+
provider.add_span_processor(BatchSpanProcessor(exporter))
|
|
193
|
+
trace.set_tracer_provider(provider)
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
**Filter patterns:**
|
|
197
|
+
|
|
198
|
+
- `"invoke_llm"` — exact match
|
|
199
|
+
- `"adk.before*"` — prefix wildcard, drops any span starting with `adk.before`
|
|
200
|
+
- `"llm.*"` — prefix wildcard, drops any span starting with `llm.`
|
|
201
|
+
|
|
170
202
|
## Testing
|
|
171
203
|
|
|
172
204
|
To run the SDK tests, execute:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|