langtrace-python-sdk 2.1.16__py3-none-any.whl → 2.1.19__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.
Files changed (39) hide show
  1. examples/inspect_ai_example/basic_eval.py +24 -0
  2. examples/langchain_example/basic.py +23 -8
  3. examples/llamaindex_example/agent.py +1 -1
  4. examples/llamaindex_example/basic.py +5 -1
  5. examples/ollama_example/__init__.py +14 -0
  6. examples/ollama_example/basic.py +50 -0
  7. examples/openai_example/chat_completion.py +1 -1
  8. examples/pinecone_example/basic.py +1 -0
  9. langtrace_python_sdk/__init__.py +4 -5
  10. langtrace_python_sdk/constants/instrumentation/common.py +1 -0
  11. langtrace_python_sdk/constants/instrumentation/ollama.py +7 -0
  12. langtrace_python_sdk/constants/instrumentation/pinecone.py +1 -1
  13. langtrace_python_sdk/extensions/langtrace_filesystem.py +194 -0
  14. langtrace_python_sdk/instrumentation/__init__.py +2 -0
  15. langtrace_python_sdk/instrumentation/chroma/patch.py +7 -3
  16. langtrace_python_sdk/instrumentation/groq/patch.py +5 -2
  17. langtrace_python_sdk/instrumentation/langchain/patch.py +8 -2
  18. langtrace_python_sdk/instrumentation/langchain_community/patch.py +8 -2
  19. langtrace_python_sdk/instrumentation/langchain_core/patch.py +13 -3
  20. langtrace_python_sdk/instrumentation/langgraph/patch.py +7 -2
  21. langtrace_python_sdk/instrumentation/llamaindex/patch.py +7 -3
  22. langtrace_python_sdk/instrumentation/ollama/__init__.py +3 -0
  23. langtrace_python_sdk/instrumentation/ollama/instrumentation.py +58 -0
  24. langtrace_python_sdk/instrumentation/ollama/patch.py +215 -0
  25. langtrace_python_sdk/instrumentation/openai/patch.py +20 -8
  26. langtrace_python_sdk/instrumentation/pinecone/instrumentation.py +0 -1
  27. langtrace_python_sdk/instrumentation/pinecone/patch.py +7 -3
  28. langtrace_python_sdk/instrumentation/qdrant/patch.py +7 -2
  29. langtrace_python_sdk/instrumentation/weaviate/patch.py +7 -3
  30. langtrace_python_sdk/langtrace.py +14 -2
  31. langtrace_python_sdk/types/__init__.py +77 -1
  32. langtrace_python_sdk/utils/langtrace_sampler.py +56 -0
  33. langtrace_python_sdk/utils/with_root_span.py +11 -2
  34. langtrace_python_sdk/version.py +1 -1
  35. {langtrace_python_sdk-2.1.16.dist-info → langtrace_python_sdk-2.1.19.dist-info}/METADATA +3 -1
  36. {langtrace_python_sdk-2.1.16.dist-info → langtrace_python_sdk-2.1.19.dist-info}/RECORD +39 -29
  37. langtrace_python_sdk-2.1.19.dist-info/entry_points.txt +2 -0
  38. {langtrace_python_sdk-2.1.16.dist-info → langtrace_python_sdk-2.1.19.dist-info}/WHEEL +0 -0
  39. {langtrace_python_sdk-2.1.16.dist-info → langtrace_python_sdk-2.1.19.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,24 @@
1
+ # langtrace.init(write_spans_to_console=True)
2
+ import fsspec
3
+ from inspect_ai import Task, task
4
+ from inspect_ai.dataset import csv_dataset
5
+ from inspect_ai.scorer import model_graded_qa
6
+ from inspect_ai.solver import chain_of_thought, generate, self_critique
7
+
8
+ from langtrace_python_sdk.extensions.langtrace_filesystem import LangTraceFileSystem
9
+
10
+ # from langtrace_python_sdk import langtrace
11
+
12
+
13
+ # Manually register the filesystem with fsspec
14
+ # Note: This is only necessary because the filesystem is not registered.
15
+ fsspec.register_implementation(LangTraceFileSystem.protocol, LangTraceFileSystem)
16
+
17
+
18
+ @task
19
+ def security_guide():
20
+ return Task(
21
+ dataset=csv_dataset("langtracefs://clxc2mxu6000lpc7ntsvcjvp9"),
22
+ plan=[chain_of_thought(), self_critique()],
23
+ scorer=model_graded_qa(),
24
+ )
@@ -8,14 +8,15 @@ from langchain_core.runnables import RunnablePassthrough
8
8
  from langchain_openai import ChatOpenAI, OpenAIEmbeddings
9
9
 
10
10
  from langtrace_python_sdk import langtrace
11
- from langtrace_python_sdk.utils.with_root_span import (
12
- with_langtrace_root_span,
13
- with_additional_attributes,
14
- )
11
+ from langtrace_python_sdk.utils.with_root_span import with_langtrace_root_span
12
+ from openai import OpenAI
15
13
 
16
14
  _ = load_dotenv(find_dotenv())
17
15
 
18
- langtrace.init()
16
+ langtrace.init(
17
+ write_spans_to_console=False,
18
+ disable_tracing_for_functions={"langchain": ["RunnableSequence.invoke"]},
19
+ )
19
20
 
20
21
 
21
22
  def api_call_1():
@@ -29,7 +30,8 @@ def api_call_1():
29
30
  output_parser = StrOutputParser()
30
31
  chain = prompt | llm | output_parser
31
32
  res = chain.invoke({"input": "how can langsmith help with testing?"})
32
- print(res)
33
+ # print(res)
34
+ return res
33
35
 
34
36
 
35
37
  def api_call_2():
@@ -43,13 +45,26 @@ def api_call_2():
43
45
  output_parser = StrOutputParser()
44
46
  chain = prompt | llm | output_parser
45
47
  res = chain.invoke({"input": "how can langsmith help with testing?"})
46
- print(res)
48
+ # print(res)
49
+ return res
47
50
 
48
51
 
49
52
  @with_langtrace_root_span()
50
53
  def basic_app():
51
54
  api_call_1()
52
- api_call_2()
55
+ # api_call_2()
56
+ client = OpenAI()
57
+ response = client.chat.completions.create(
58
+ model="gpt-4",
59
+ messages=[
60
+ {"role": "system", "content": "Talk like a pirate"},
61
+ {"role": "user", "content": "Tell me a story in 3 sentences or less."},
62
+ ],
63
+ # stream=True,
64
+ stream=False,
65
+ )
66
+
67
+ return response
53
68
 
54
69
 
55
70
  @with_langtrace_root_span()
@@ -12,7 +12,7 @@ import nest_asyncio
12
12
 
13
13
  nest_asyncio.apply()
14
14
 
15
- langtrace.init(write_spans_to_console=False)
15
+ langtrace.init()
16
16
 
17
17
 
18
18
  def multiply(a: int, b: int) -> int:
@@ -7,7 +7,11 @@ from langtrace_python_sdk.utils.with_root_span import with_langtrace_root_span
7
7
  _ = load_dotenv(find_dotenv())
8
8
 
9
9
 
10
- langtrace.init(write_spans_to_console=False)
10
+ langtrace.init(
11
+ disable_tracing_for_functions={
12
+ "open_ai": ["openai.chat.completions.create"],
13
+ }
14
+ )
11
15
 
12
16
 
13
17
  @with_langtrace_root_span()
@@ -0,0 +1,14 @@
1
+ from .basic import chat, async_chat, async_generate, generate, embed, async_embed
2
+ from langtrace_python_sdk import with_langtrace_root_span
3
+ import asyncio
4
+
5
+
6
+ class OllamaRunner:
7
+ @with_langtrace_root_span("OllamaRunner")
8
+ def run(self):
9
+ chat()
10
+ generate()
11
+ embed()
12
+ asyncio.run(async_chat())
13
+ asyncio.run(async_generate())
14
+ asyncio.run(async_embed())
@@ -0,0 +1,50 @@
1
+ from langtrace_python_sdk import langtrace, with_langtrace_root_span
2
+ import ollama
3
+ from ollama import AsyncClient
4
+ from dotenv import load_dotenv
5
+
6
+ load_dotenv()
7
+
8
+ langtrace.init(write_spans_to_console=False)
9
+
10
+
11
+ def chat():
12
+ response = ollama.chat(
13
+ model="llama3",
14
+ messages=[
15
+ {
16
+ "role": "user",
17
+ "content": "hi",
18
+ },
19
+ ],
20
+ stream=True,
21
+ )
22
+
23
+ return response
24
+
25
+
26
+ async def async_chat():
27
+ message = {"role": "user", "content": "Why is the sky blue?"}
28
+ return await AsyncClient().chat(model="llama3", messages=[message])
29
+
30
+
31
+ def generate():
32
+ return ollama.generate(model="llama3", prompt="Why is the sky blue?")
33
+
34
+
35
+ def async_generate():
36
+ return AsyncClient().generate(model="llama3", prompt="Why is the sky blue?")
37
+
38
+
39
+ def embed():
40
+ return ollama.embeddings(
41
+ model="llama3",
42
+ prompt="cat",
43
+ )
44
+
45
+
46
+ async def async_embed():
47
+ return await AsyncClient().embeddings(
48
+ model="llama3",
49
+ prompt="cat",
50
+ )
@@ -40,5 +40,5 @@ def chat_completion():
40
40
  ]
41
41
  result.append(content[0] if len(content) > 0 else "")
42
42
 
43
- print("".join(result))
43
+ # print("".join(result))
44
44
  return response
@@ -13,6 +13,7 @@ from langtrace_python_sdk import (
13
13
  with_additional_attributes,
14
14
  )
15
15
  from langtrace_python_sdk.utils.with_root_span import SendUserFeedback
16
+ from opentelemetry.sdk.trace.export import ConsoleSpanExporter
16
17
 
17
18
  _ = load_dotenv(find_dotenv())
18
19
  langtrace.init()
@@ -15,15 +15,13 @@ limitations under the License.
15
15
  """
16
16
 
17
17
  from langtrace_python_sdk import langtrace
18
- from langtrace_python_sdk.utils.with_root_span import (
19
- with_langtrace_root_span,
20
- with_additional_attributes,
21
- )
22
-
18
+ from langtrace_python_sdk.extensions.langtrace_filesystem import LangTraceFileSystem
23
19
  from langtrace_python_sdk.utils.prompt_registry import get_prompt_from_registry
24
20
  from langtrace_python_sdk.utils.with_root_span import (
25
21
  SendUserFeedback,
26
22
  inject_additional_attributes,
23
+ with_additional_attributes,
24
+ with_langtrace_root_span,
27
25
  )
28
26
 
29
27
  __all__ = [
@@ -33,4 +31,5 @@ __all__ = [
33
31
  "inject_additional_attributes",
34
32
  "get_prompt_from_registry",
35
33
  "SendUserFeedback",
34
+ "LangTraceFileSystem",
36
35
  ]
@@ -23,6 +23,7 @@ SERVICE_PROVIDERS = {
23
23
  "PPLX": "Perplexity",
24
24
  "QDRANT": "Qdrant",
25
25
  "WEAVIATE": "Weaviate",
26
+ "OLLAMA": "Ollama",
26
27
  }
27
28
 
28
29
  LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY = "langtrace_additional_attributes"
@@ -0,0 +1,7 @@
1
+ APIS = {
2
+ "GENERATE": {
3
+ "METHOD": "generate",
4
+ },
5
+ "CHAT": {"METHOD": "chat"},
6
+ "EMBEDDINGS": {"METHOD": "embeddings"},
7
+ }
@@ -12,7 +12,7 @@ APIS = {
12
12
  "OPERATION": "query",
13
13
  },
14
14
  "DELETE": {
15
- "METHOD": PineconeMethods.DELETE,
15
+ "METHOD": PineconeMethods.DELETE.value,
16
16
  "ENDPOINT": "/vectors/delete",
17
17
  "OPERATION": "delete",
18
18
  },
@@ -0,0 +1,194 @@
1
+ import json
2
+ import io
3
+ import os
4
+ import requests
5
+ from typing import Iterator, Literal, Union
6
+ from colorama import Fore
7
+ from langtrace_python_sdk.constants.exporter.langtrace_exporter import (
8
+ LANGTRACE_REMOTE_URL,
9
+ )
10
+ from fsspec.spec import AbstractFileSystem
11
+
12
+ OpenTextMode = Literal["r", "a", "w"]
13
+ OpenBinaryMode = Literal["rb", "ab", "wb"]
14
+
15
+
16
+ class OpenMode(str):
17
+ def __init_subclass__(cls, **kwargs):
18
+ allowed_values = Union[set(OpenTextMode.__args__), set(OpenBinaryMode.__args__)]
19
+ super().__init_subclass__(**kwargs)
20
+
21
+ def __new__(cls, value):
22
+ if value not in allowed_values:
23
+ raise ValueError(f"Invalid value for OpenMode: {value}")
24
+ return super().__new__(cls, value)
25
+
26
+ cls.__new__ = __new__
27
+
28
+
29
+ class LangTraceFile(io.BytesIO):
30
+ def __init__(self, fs: "LangTraceFileSystem", path: str, mode: OpenMode):
31
+ super().__init__()
32
+ self.fs = fs
33
+ self.path = path
34
+ self.mode = mode
35
+
36
+ def close(self) -> None:
37
+ if not self.closed:
38
+ self.seek(0)
39
+ file_data = self.getvalue()
40
+ self.fs.files[self.path] = file_data
41
+
42
+ # Upload the file to the remote server
43
+ self.upload_to_server(file_data)
44
+
45
+ super().close()
46
+
47
+ def upload_to_server(self, file_data: bytes) -> None:
48
+ try:
49
+ # Parse the log file and upload it to the server
50
+ log = file_data.decode("utf-8")
51
+ eval_log = json.loads(log)
52
+ data = {
53
+ "runId": eval_log["eval"]["run_id"],
54
+ "taskId": eval_log["eval"]["task_id"],
55
+ "log": log,
56
+ }
57
+ if self.path is not None:
58
+ dataset_id = self.path.split("/")[0]
59
+ print(
60
+ Fore.GREEN
61
+ + f"Sending results to Langtrace for dataset: {dataset_id}"
62
+ + Fore.RESET
63
+ )
64
+ data["datasetId"] = dataset_id
65
+ else:
66
+ print(Fore.GREEN + "Sending results to Langtrace" + Fore.RESET)
67
+ response = requests.post(
68
+ url=f"{LANGTRACE_REMOTE_URL}/api/run",
69
+ data=json.dumps(data),
70
+ headers={
71
+ "Content-Type": "application/json",
72
+ "x-api-key": os.environ.get("LANGTRACE_API_KEY"),
73
+ },
74
+ timeout=20,
75
+ )
76
+ response.raise_for_status()
77
+ print(Fore.GREEN + "Results sent to Langtrace successfully." + Fore.RESET)
78
+ except requests.exceptions.RequestException as error:
79
+ print(Fore.RED + f"Error reporting results: {error}" + Fore.RESET)
80
+
81
+
82
+ class LangTraceFileSystem(AbstractFileSystem):
83
+ protocol = "langtracefs"
84
+ sep = "/"
85
+
86
+ def __init__(self, *args, **kwargs):
87
+ super().__init__(*args, **kwargs)
88
+ self.files = {}
89
+ self.dirs = set()
90
+
91
+ def open(
92
+ self,
93
+ path: str,
94
+ mode: Union[OpenTextMode, OpenBinaryMode] = "rb",
95
+ **kwargs,
96
+ ) -> Iterator[Union[LangTraceFile, io.BytesIO]]:
97
+ if "r" in mode:
98
+ dataset_id = path
99
+ # Fetch file from API and return a BytesIO object
100
+ file_data = self.fetch_file_from_api(dataset_id)
101
+ return io.BytesIO(file_data)
102
+ elif "w" in mode or "a" in mode:
103
+ return LangTraceFile(self, path, mode)
104
+ else:
105
+ raise ValueError(f"Unsupported mode: {mode}")
106
+
107
+ def fetch_file_from_api(self, dataset_id: str) -> bytes:
108
+ try:
109
+ print(
110
+ Fore.GREEN
111
+ + f"Fetching dataset with id: {dataset_id} from Langtrace"
112
+ + Fore.RESET
113
+ )
114
+ response = requests.get(
115
+ url=f"{LANGTRACE_REMOTE_URL}/api/dataset/download?id={dataset_id}",
116
+ headers={
117
+ "Content-Type": "application/json",
118
+ "x-api-key": os.environ.get("LANGTRACE_API_KEY"),
119
+ },
120
+ timeout=20,
121
+ )
122
+ print(
123
+ Fore.GREEN
124
+ + f"Successfully fetched dataset with id: {dataset_id} from Langtrace"
125
+ + Fore.RESET
126
+ )
127
+ response.raise_for_status()
128
+ file_data = response.content
129
+ return file_data
130
+ except requests.exceptions.RequestException as error:
131
+ print(
132
+ Fore.RED
133
+ + f"Error fetching dataset with id: {dataset_id} from Langtrace: {error}"
134
+ + Fore.RESET
135
+ )
136
+ return b""
137
+
138
+ def makedirs(self, path: str, exist_ok: bool = False) -> None:
139
+ if not exist_ok and path in self.dirs:
140
+ raise FileExistsError(f"Directory {path} already exists")
141
+ self.dirs.add(path)
142
+
143
+ def info(self, path: str, **kwargs):
144
+ if path in self.files:
145
+ return {"name": path, "size": len(self.files[path]), "type": "file"}
146
+ elif path in self.dirs:
147
+ return {"name": path, "type": "directory"}
148
+ else:
149
+ raise FileNotFoundError(f"No such file or directory: {path}")
150
+
151
+ def created(self, path: str) -> float:
152
+ # Return a dummy creation time
153
+ return 0.0
154
+
155
+ def exists(self, path: str) -> bool:
156
+ return path in self.files or path in self.dirs
157
+
158
+ def ls(self, path: str, detail: bool = False, **kwargs):
159
+ if path not in self.dirs:
160
+ raise FileNotFoundError(f"No such directory: {path}")
161
+ entries = []
162
+ for file_path in self.files:
163
+ if file_path.startswith(path + self.sep):
164
+ if detail:
165
+ entries.append(self.info(file_path))
166
+ else:
167
+ entries.append(file_path)
168
+ for dir_path in self.dirs:
169
+ if dir_path.startswith(path + self.sep):
170
+ if detail:
171
+ entries.append(self.info(dir_path))
172
+ else:
173
+ entries.append(dir_path)
174
+ return entries
175
+
176
+ def walk(self, path: str, maxdepth: int = None, **kwargs):
177
+ for root, dirs, files in self._walk(path):
178
+ yield root, dirs, [self.sep.join([root, f]) for f in files]
179
+
180
+ def _walk(self, path: str):
181
+ if path in self.dirs:
182
+ dirs = [d for d in self.dirs if d.startswith(path + self.sep)]
183
+ files = [f for f in self.files if f.startswith(path + self.sep)]
184
+ yield path, [d.split(self.sep)[-1] for d in dirs], [
185
+ f.split(self.sep)[-1] for f in files
186
+ ]
187
+ for d in dirs:
188
+ yield from self._walk(d)
189
+
190
+ def unstrip_protocol(self, path: str) -> str:
191
+ return path
192
+
193
+ def invalidate_cache(self, path: str = None) -> None:
194
+ pass
@@ -11,6 +11,7 @@ from .openai import OpenAIInstrumentation
11
11
  from .pinecone import PineconeInstrumentation
12
12
  from .qdrant import QdrantInstrumentation
13
13
  from .weaviate import WeaviateInstrumentation
14
+ from .ollama import OllamaInstrumentor
14
15
 
15
16
  __all__ = [
16
17
  "AnthropicInstrumentation",
@@ -26,4 +27,5 @@ __all__ = [
26
27
  "PineconeInstrumentation",
27
28
  "QdrantInstrumentation",
28
29
  "WeaviateInstrumentation",
30
+ "OllamaInstrumentor",
29
31
  ]
@@ -17,10 +17,10 @@ limitations under the License.
17
17
  from langtrace.trace_attributes import DatabaseSpanAttributes
18
18
  from langtrace_python_sdk.utils.llm import set_span_attributes
19
19
  from langtrace_python_sdk.utils.silently_fail import silently_fail
20
- from opentelemetry import baggage
20
+ from opentelemetry import baggage, trace
21
21
  from opentelemetry.trace import SpanKind
22
22
  from opentelemetry.trace.status import Status, StatusCode
23
-
23
+ from opentelemetry.trace.propagation import set_span_in_context
24
24
  from langtrace_python_sdk.constants.instrumentation.chroma import APIS
25
25
  from langtrace_python_sdk.constants.instrumentation.common import (
26
26
  LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY,
@@ -59,7 +59,11 @@ def collection_patch(method, version, tracer):
59
59
 
60
60
  attributes = DatabaseSpanAttributes(**span_attributes)
61
61
 
62
- with tracer.start_as_current_span(api["METHOD"], kind=SpanKind.CLIENT) as span:
62
+ with tracer.start_as_current_span(
63
+ api["METHOD"],
64
+ kind=SpanKind.CLIENT,
65
+ context=set_span_in_context(trace.get_current_span()),
66
+ ) as span:
63
67
  for field, value in attributes.model_dump(by_alias=True).items():
64
68
  if value is not None:
65
69
  span.set_attribute(field, value)
@@ -17,7 +17,8 @@ limitations under the License.
17
17
  import json
18
18
 
19
19
  from langtrace.trace_attributes import Event, LLMSpanAttributes
20
- from opentelemetry import baggage
20
+ from opentelemetry import baggage, trace
21
+ from opentelemetry.trace.propagation import set_span_in_context
21
22
  from opentelemetry.trace import SpanKind
22
23
  from opentelemetry.trace.status import Status, StatusCode
23
24
 
@@ -112,7 +113,9 @@ def chat_completions_create(original_method, version, tracer):
112
113
  # with tracer.start_as_current_span(APIS["CHAT_COMPLETION"]["METHOD"],
113
114
  # kind=SpanKind.CLIENT) as span:
114
115
  span = tracer.start_span(
115
- APIS["CHAT_COMPLETION"]["METHOD"], kind=SpanKind.CLIENT
116
+ APIS["CHAT_COMPLETION"]["METHOD"],
117
+ kind=SpanKind.CLIENT,
118
+ context=set_span_in_context(trace.get_current_span()),
116
119
  )
117
120
  for field, value in attributes.model_dump(by_alias=True).items():
118
121
  if value is not None:
@@ -17,7 +17,9 @@ limitations under the License.
17
17
  import json
18
18
 
19
19
  from langtrace.trace_attributes import FrameworkSpanAttributes
20
- from opentelemetry import baggage
20
+ from langtrace_python_sdk.constants import LANGTRACE_SDK_NAME
21
+ from opentelemetry import baggage, trace
22
+ from opentelemetry.trace.propagation import set_span_in_context
21
23
  from opentelemetry.trace import SpanKind, StatusCode
22
24
  from opentelemetry.trace.status import Status
23
25
 
@@ -54,7 +56,11 @@ def generic_patch(
54
56
 
55
57
  attributes = FrameworkSpanAttributes(**span_attributes)
56
58
 
57
- with tracer.start_as_current_span(method_name, kind=SpanKind.CLIENT) as span:
59
+ with tracer.start_as_current_span(
60
+ method_name,
61
+ kind=SpanKind.CLIENT,
62
+ context=set_span_in_context(trace.get_current_span()),
63
+ ) as span:
58
64
  for field, value in attributes.model_dump(by_alias=True).items():
59
65
  if value is not None:
60
66
  span.set_attribute(field, value)
@@ -17,7 +17,9 @@ limitations under the License.
17
17
  import json
18
18
 
19
19
  from langtrace.trace_attributes import FrameworkSpanAttributes
20
- from opentelemetry import baggage
20
+ from opentelemetry import baggage, trace
21
+ from opentelemetry.trace.propagation import set_span_in_context
22
+
21
23
  from opentelemetry.trace import SpanKind
22
24
  from opentelemetry.trace.status import Status, StatusCode
23
25
 
@@ -52,7 +54,11 @@ def generic_patch(
52
54
 
53
55
  attributes = FrameworkSpanAttributes(**span_attributes)
54
56
 
55
- with tracer.start_as_current_span(method_name, kind=SpanKind.CLIENT) as span:
57
+ with tracer.start_as_current_span(
58
+ method_name,
59
+ kind=SpanKind.CLIENT,
60
+ context=set_span_in_context(trace.get_current_span()),
61
+ ) as span:
56
62
  for field, value in attributes.model_dump(by_alias=True).items():
57
63
  if value is not None:
58
64
  span.set_attribute(field, value)
@@ -17,9 +17,10 @@ limitations under the License.
17
17
  import json
18
18
 
19
19
  from langtrace.trace_attributes import FrameworkSpanAttributes
20
- from opentelemetry import baggage
20
+ from opentelemetry import baggage, trace
21
21
  from opentelemetry.trace import SpanKind, StatusCode
22
22
  from opentelemetry.trace.status import Status
23
+ from opentelemetry.trace.propagation import set_span_in_context
23
24
 
24
25
  from langtrace_python_sdk.constants.instrumentation.common import (
25
26
  LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY,
@@ -73,7 +74,12 @@ def generic_patch(
73
74
 
74
75
  attributes = FrameworkSpanAttributes(**span_attributes)
75
76
 
76
- with tracer.start_as_current_span(method_name, kind=SpanKind.CLIENT) as span:
77
+ with tracer.start_as_current_span(
78
+ method_name,
79
+ kind=SpanKind.CLIENT,
80
+ context=set_span_in_context(trace.get_current_span()),
81
+ ) as span:
82
+
77
83
  for field, value in attributes.model_dump(by_alias=True).items():
78
84
  if value is not None:
79
85
  span.set_attribute(field, value)
@@ -147,7 +153,11 @@ def runnable_patch(
147
153
 
148
154
  attributes = FrameworkSpanAttributes(**span_attributes)
149
155
 
150
- with tracer.start_as_current_span(method_name, kind=SpanKind.CLIENT) as span:
156
+ with tracer.start_as_current_span(
157
+ method_name,
158
+ kind=SpanKind.CLIENT,
159
+ context=set_span_in_context(trace.get_current_span()),
160
+ ) as span:
151
161
  for field, value in attributes.model_dump(by_alias=True).items():
152
162
  if value is not None:
153
163
  span.set_attribute(field, value)
@@ -15,9 +15,10 @@ limitations under the License.
15
15
  """
16
16
 
17
17
  import json
18
+ from opentelemetry.trace.propagation import set_span_in_context
18
19
 
19
20
  from langtrace.trace_attributes import FrameworkSpanAttributes
20
- from opentelemetry import baggage
21
+ from opentelemetry import baggage, trace
21
22
  from opentelemetry.trace import SpanKind
22
23
  from opentelemetry.trace.status import Status, StatusCode
23
24
 
@@ -50,7 +51,11 @@ def patch_graph_methods(method_name, tracer, version):
50
51
 
51
52
  attributes = FrameworkSpanAttributes(**span_attributes)
52
53
 
53
- with tracer.start_as_current_span(method_name, kind=SpanKind.CLIENT) as span:
54
+ with tracer.start_as_current_span(
55
+ method_name,
56
+ kind=SpanKind.CLIENT,
57
+ context=set_span_in_context(trace.get_current_span()),
58
+ ) as span:
54
59
  for field, value in attributes.model_dump(by_alias=True).items():
55
60
  if value is not None:
56
61
  span.set_attribute(field, value)
@@ -15,10 +15,10 @@ limitations under the License.
15
15
  """
16
16
 
17
17
  from langtrace.trace_attributes import FrameworkSpanAttributes
18
- from opentelemetry import baggage
18
+ from opentelemetry import baggage, trace
19
19
  from opentelemetry.trace import SpanKind
20
20
  from opentelemetry.trace.status import Status, StatusCode
21
-
21
+ from opentelemetry.trace.propagation import set_span_in_context
22
22
  from langtrace_python_sdk.constants.instrumentation.common import (
23
23
  LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY,
24
24
  SERVICE_PROVIDERS,
@@ -48,7 +48,11 @@ def generic_patch(method, task, tracer, version):
48
48
 
49
49
  attributes = FrameworkSpanAttributes(**span_attributes)
50
50
 
51
- with tracer.start_as_current_span(method, kind=SpanKind.CLIENT) as span:
51
+ with tracer.start_as_current_span(
52
+ method,
53
+ kind=SpanKind.CLIENT,
54
+ context=set_span_in_context(trace.get_current_span()),
55
+ ) as span:
52
56
  for field, value in attributes.model_dump(by_alias=True).items():
53
57
  if value is not None:
54
58
  span.set_attribute(field, value)
@@ -0,0 +1,3 @@
1
+ from .instrumentation import OllamaInstrumentor
2
+
3
+ __all__ = ["OllamaInstrumentor"]