lmnr 0.5.3__py3-none-any.whl → 0.6.1__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.
- lmnr/__init__.py +6 -1
- lmnr/opentelemetry_lib/__init__.py +23 -36
- lmnr/opentelemetry_lib/decorators/__init__.py +219 -0
- lmnr/opentelemetry_lib/tracing/__init__.py +158 -1
- lmnr/opentelemetry_lib/tracing/_instrument_initializers.py +398 -0
- lmnr/opentelemetry_lib/tracing/attributes.py +14 -7
- lmnr/opentelemetry_lib/tracing/context_properties.py +53 -0
- lmnr/opentelemetry_lib/tracing/exporter.py +60 -0
- lmnr/opentelemetry_lib/tracing/instruments.py +121 -0
- lmnr/opentelemetry_lib/tracing/processor.py +96 -0
- lmnr/opentelemetry_lib/tracing/{context_manager.py → tracer.py} +6 -1
- lmnr/opentelemetry_lib/utils/package_check.py +3 -1
- lmnr/sdk/browser/browser_use_otel.py +1 -1
- lmnr/sdk/browser/playwright_otel.py +22 -7
- lmnr/sdk/browser/pw_utils.py +25 -9
- lmnr/sdk/client/asynchronous/resources/agent.py +3 -1
- lmnr/sdk/client/synchronous/resources/agent.py +3 -1
- lmnr/sdk/decorators.py +4 -2
- lmnr/sdk/evaluations.py +3 -3
- lmnr/sdk/laminar.py +28 -31
- lmnr/sdk/utils.py +2 -3
- lmnr/version.py +1 -1
- {lmnr-0.5.3.dist-info → lmnr-0.6.1.dist-info}/METADATA +65 -62
- {lmnr-0.5.3.dist-info → lmnr-0.6.1.dist-info}/RECORD +27 -28
- lmnr/opentelemetry_lib/config/__init__.py +0 -12
- lmnr/opentelemetry_lib/decorators/base.py +0 -210
- lmnr/opentelemetry_lib/instruments.py +0 -42
- lmnr/opentelemetry_lib/tracing/content_allow_list.py +0 -24
- lmnr/opentelemetry_lib/tracing/tracing.py +0 -1016
- lmnr/opentelemetry_lib/utils/in_memory_span_exporter.py +0 -61
- {lmnr-0.5.3.dist-info → lmnr-0.6.1.dist-info}/LICENSE +0 -0
- {lmnr-0.5.3.dist-info → lmnr-0.6.1.dist-info}/WHEEL +0 -0
- {lmnr-0.5.3.dist-info → lmnr-0.6.1.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,96 @@
|
|
1
|
+
import uuid
|
2
|
+
|
3
|
+
from typing import Optional, Union
|
4
|
+
from opentelemetry.sdk.trace.export import (
|
5
|
+
SpanProcessor,
|
6
|
+
SpanExporter,
|
7
|
+
BatchSpanProcessor,
|
8
|
+
SimpleSpanProcessor,
|
9
|
+
)
|
10
|
+
from opentelemetry.trace import Span
|
11
|
+
from opentelemetry.context import Context, get_value, get_current, set_value
|
12
|
+
|
13
|
+
from lmnr.opentelemetry_lib.tracing.attributes import (
|
14
|
+
SPAN_IDS_PATH,
|
15
|
+
SPAN_INSTRUMENTATION_SOURCE,
|
16
|
+
SPAN_LANGUAGE_VERSION,
|
17
|
+
SPAN_PATH,
|
18
|
+
SPAN_SDK_VERSION,
|
19
|
+
)
|
20
|
+
from lmnr.opentelemetry_lib.tracing.exporter import LaminarSpanExporter
|
21
|
+
from lmnr.opentelemetry_lib.tracing.context_properties import (
|
22
|
+
_set_association_properties_attributes,
|
23
|
+
)
|
24
|
+
from lmnr.version import PYTHON_VERSION, __version__
|
25
|
+
|
26
|
+
|
27
|
+
class LaminarSpanProcessor(SpanProcessor):
|
28
|
+
instance: Union[BatchSpanProcessor, SimpleSpanProcessor]
|
29
|
+
__span_id_to_path: dict[int, list[str]] = {}
|
30
|
+
__span_id_lists: dict[int, list[str]] = {}
|
31
|
+
|
32
|
+
def __init__(
|
33
|
+
self,
|
34
|
+
base_url: Optional[str] = None,
|
35
|
+
port: Optional[int] = None,
|
36
|
+
api_key: Optional[str] = None,
|
37
|
+
timeout_seconds: int = 30,
|
38
|
+
force_http: bool = False,
|
39
|
+
max_export_batch_size: int = 512,
|
40
|
+
disable_batch: bool = False,
|
41
|
+
exporter: Optional[SpanExporter] = None,
|
42
|
+
):
|
43
|
+
self.exporter = exporter or LaminarSpanExporter(
|
44
|
+
base_url=base_url,
|
45
|
+
port=port,
|
46
|
+
api_key=api_key,
|
47
|
+
timeout_seconds=timeout_seconds,
|
48
|
+
force_http=force_http,
|
49
|
+
)
|
50
|
+
self.instance = (
|
51
|
+
SimpleSpanProcessor(self.exporter)
|
52
|
+
if disable_batch
|
53
|
+
else BatchSpanProcessor(
|
54
|
+
self.exporter, max_export_batch_size=max_export_batch_size
|
55
|
+
)
|
56
|
+
)
|
57
|
+
|
58
|
+
def on_start(self, span: Span, parent_context: Optional[Context] = None):
|
59
|
+
span_path_in_context = get_value("span_path", parent_context or get_current())
|
60
|
+
parent_span_path = span_path_in_context or (
|
61
|
+
self.__span_id_to_path.get(span.parent.span_id) if span.parent else None
|
62
|
+
)
|
63
|
+
parent_span_ids_path = (
|
64
|
+
self.__span_id_lists.get(span.parent.span_id, []) if span.parent else []
|
65
|
+
)
|
66
|
+
span_path = parent_span_path + [span.name] if parent_span_path else [span.name]
|
67
|
+
span_ids_path = parent_span_ids_path + [
|
68
|
+
str(uuid.UUID(int=span.get_span_context().span_id))
|
69
|
+
]
|
70
|
+
span.set_attribute(SPAN_PATH, span_path)
|
71
|
+
span.set_attribute(SPAN_IDS_PATH, span_ids_path)
|
72
|
+
set_value("span_path", span_path, get_current())
|
73
|
+
self.__span_id_to_path[span.get_span_context().span_id] = span_path
|
74
|
+
self.__span_id_lists[span.get_span_context().span_id] = span_ids_path
|
75
|
+
|
76
|
+
span.set_attribute(SPAN_INSTRUMENTATION_SOURCE, "python")
|
77
|
+
span.set_attribute(SPAN_SDK_VERSION, __version__)
|
78
|
+
span.set_attribute(SPAN_LANGUAGE_VERSION, f"python@{PYTHON_VERSION}")
|
79
|
+
|
80
|
+
association_properties = get_value("association_properties")
|
81
|
+
if association_properties is not None:
|
82
|
+
_set_association_properties_attributes(span, association_properties)
|
83
|
+
self.instance.on_start(span, parent_context)
|
84
|
+
|
85
|
+
def on_end(self, span: Span):
|
86
|
+
self.instance.on_end(span)
|
87
|
+
|
88
|
+
def force_flush(self, timeout_millis: int = 30000) -> bool:
|
89
|
+
return self.instance.force_flush(timeout_millis)
|
90
|
+
|
91
|
+
def shutdown(self):
|
92
|
+
self.instance.shutdown()
|
93
|
+
|
94
|
+
def clear(self):
|
95
|
+
self.__span_id_to_path = {}
|
96
|
+
self.__span_id_lists = {}
|
@@ -1,6 +1,11 @@
|
|
1
1
|
from contextlib import contextmanager
|
2
2
|
|
3
|
-
from
|
3
|
+
from opentelemetry import trace
|
4
|
+
from lmnr.opentelemetry_lib.tracing import TracerWrapper
|
5
|
+
|
6
|
+
|
7
|
+
def get_laminar_tracer_provider() -> trace.TracerProvider:
|
8
|
+
return TracerWrapper.instance.__tracer_provider or trace.get_tracer_provider()
|
4
9
|
|
5
10
|
|
6
11
|
@contextmanager
|
@@ -1,6 +1,8 @@
|
|
1
1
|
from importlib.metadata import distributions
|
2
2
|
|
3
|
-
installed_packages = {
|
3
|
+
installed_packages = {
|
4
|
+
(dist.name or dist.metadata.get("Name", "")).lower() for dist in distributions()
|
5
|
+
}
|
4
6
|
|
5
7
|
|
6
8
|
def is_package_installed(package_name: str) -> bool:
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import logging
|
2
2
|
import uuid
|
3
3
|
|
4
|
+
from lmnr.opentelemetry_lib.utils.package_check import is_package_installed
|
4
5
|
from lmnr.sdk.browser.pw_utils import handle_navigation_async, handle_navigation_sync
|
5
6
|
from lmnr.sdk.browser.utils import with_tracer_and_client_wrapper
|
6
7
|
from lmnr.sdk.client.asynchronous.async_client import AsyncLaminarClient
|
@@ -22,17 +23,31 @@ from typing import Collection
|
|
22
23
|
from wrapt import wrap_function_wrapper
|
23
24
|
|
24
25
|
try:
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
26
|
+
if is_package_installed("playwright"):
|
27
|
+
from playwright.async_api import Browser, BrowserContext, Page
|
28
|
+
from playwright.sync_api import (
|
29
|
+
Browser as SyncBrowser,
|
30
|
+
BrowserContext as SyncBrowserContext,
|
31
|
+
Page as SyncPage,
|
32
|
+
)
|
33
|
+
elif is_package_installed("patchright"):
|
34
|
+
from patchright.async_api import Browser, BrowserContext, Page
|
35
|
+
from patchright.sync_api import (
|
36
|
+
Browser as SyncBrowser,
|
37
|
+
BrowserContext as SyncBrowserContext,
|
38
|
+
Page as SyncPage,
|
39
|
+
)
|
40
|
+
else:
|
41
|
+
raise ImportError(
|
42
|
+
"Attempted to import lmnr.sdk.browser.playwright_otel, but neither "
|
43
|
+
"playwright nor patchright is installed. Use `pip install playwright` "
|
44
|
+
"or `pip install patchright` to install one of the supported browsers."
|
45
|
+
)
|
31
46
|
except ImportError as e:
|
32
47
|
raise ImportError(
|
33
48
|
f"Attempted to import {__file__}, but it is designed "
|
34
49
|
"to patch Playwright, which is not installed. Use `pip install playwright` "
|
35
|
-
"to install Playwright or remove this import."
|
50
|
+
"or `pip install patchright` to install Playwright or remove this import."
|
36
51
|
) from e
|
37
52
|
|
38
53
|
# all available versions at https://pypi.org/project/playwright/#history
|
lmnr/sdk/browser/pw_utils.py
CHANGED
@@ -6,19 +6,31 @@ import threading
|
|
6
6
|
|
7
7
|
from opentelemetry import trace
|
8
8
|
|
9
|
+
from lmnr.opentelemetry_lib.utils.package_check import is_package_installed
|
9
10
|
from lmnr.sdk.decorators import observe
|
10
11
|
from lmnr.sdk.browser.utils import retry_sync, retry_async
|
11
12
|
from lmnr.sdk.client.synchronous.sync_client import LaminarClient
|
12
13
|
from lmnr.sdk.client.asynchronous.async_client import AsyncLaminarClient
|
13
14
|
|
15
|
+
|
14
16
|
try:
|
15
|
-
|
16
|
-
|
17
|
+
if is_package_installed("playwright"):
|
18
|
+
from playwright.async_api import Page
|
19
|
+
from playwright.sync_api import Page as SyncPage
|
20
|
+
elif is_package_installed("patchright"):
|
21
|
+
from patchright.async_api import Page
|
22
|
+
from patchright.sync_api import Page as SyncPage
|
23
|
+
else:
|
24
|
+
raise ImportError(
|
25
|
+
"Attempted to import lmnr.sdk.browser.pw_utils, but neither "
|
26
|
+
"playwright nor patchright is installed. Use `pip install playwright` "
|
27
|
+
"or `pip install patchright` to install one of the supported browsers."
|
28
|
+
)
|
17
29
|
except ImportError as e:
|
18
30
|
raise ImportError(
|
19
|
-
|
20
|
-
"
|
21
|
-
"to install
|
31
|
+
"Attempted to import lmnr.sdk.browser.pw_utils, but neither "
|
32
|
+
"playwright nor patchright is installed. Use `pip install playwright` "
|
33
|
+
"or `pip install patchright` to install one of the supported browsers."
|
22
34
|
) from e
|
23
35
|
|
24
36
|
logger = logging.getLogger(__name__)
|
@@ -100,14 +112,16 @@ async def send_events_async(
|
|
100
112
|
"""Fetch events from the page and send them to the server"""
|
101
113
|
try:
|
102
114
|
# Check if function exists first
|
103
|
-
events = await page.evaluate(
|
115
|
+
events = await page.evaluate(
|
116
|
+
"""
|
104
117
|
() => {
|
105
118
|
if (!window.lmnrPageIsFocused || typeof window.lmnrGetAndClearEvents !== 'function') {
|
106
119
|
return [];
|
107
120
|
}
|
108
121
|
return window.lmnrGetAndClearEvents();
|
109
122
|
}
|
110
|
-
"""
|
123
|
+
"""
|
124
|
+
)
|
111
125
|
|
112
126
|
if not events or len(events) == 0:
|
113
127
|
return
|
@@ -127,14 +141,16 @@ def send_events_sync(
|
|
127
141
|
):
|
128
142
|
"""Synchronous version of send_events"""
|
129
143
|
try:
|
130
|
-
events = page.evaluate(
|
144
|
+
events = page.evaluate(
|
145
|
+
"""
|
131
146
|
() => {
|
132
147
|
if (!window.lmnrPageIsFocused || typeof window.lmnrGetAndClearEvents !== 'function') {
|
133
148
|
return [];
|
134
149
|
}
|
135
150
|
return window.lmnrGetAndClearEvents();
|
136
151
|
}
|
137
|
-
"""
|
152
|
+
"""
|
153
|
+
)
|
138
154
|
if not events or len(events) == 0:
|
139
155
|
return
|
140
156
|
|
@@ -278,6 +278,8 @@ class AsyncAgent(BaseAsyncResource):
|
|
278
278
|
json=request.model_dump(by_alias=True),
|
279
279
|
headers=self._headers(),
|
280
280
|
) as response:
|
281
|
+
if response.status_code != 200:
|
282
|
+
raise RuntimeError(await response.read())
|
281
283
|
async for line in response.aiter_lines():
|
282
284
|
line = str(line)
|
283
285
|
if line.startswith("[DONE]"):
|
@@ -288,7 +290,7 @@ class AsyncAgent(BaseAsyncResource):
|
|
288
290
|
if line:
|
289
291
|
chunk = RunAgentResponseChunk.model_validate_json(line)
|
290
292
|
yield chunk.root
|
291
|
-
if chunk.root.chunk_type in ["finalOutput", "error"]:
|
293
|
+
if chunk.root.chunk_type in ["finalOutput", "error", "timeout"]:
|
292
294
|
break
|
293
295
|
|
294
296
|
async def __run_non_streaming(self, request: RunAgentRequest) -> AgentOutput:
|
@@ -270,6 +270,8 @@ class Agent(BaseResource):
|
|
270
270
|
json=request.model_dump(by_alias=True),
|
271
271
|
headers=self._headers(),
|
272
272
|
) as response:
|
273
|
+
if response.status_code != 200:
|
274
|
+
raise RuntimeError(response.read())
|
273
275
|
for line in response.iter_lines():
|
274
276
|
line = str(line)
|
275
277
|
if line.startswith("[DONE]"):
|
@@ -280,7 +282,7 @@ class Agent(BaseResource):
|
|
280
282
|
if line:
|
281
283
|
chunk = RunAgentResponseChunk.model_validate_json(line)
|
282
284
|
yield chunk.root
|
283
|
-
if chunk.root.chunk_type in ["finalOutput", "error"]:
|
285
|
+
if chunk.root.chunk_type in ["finalOutput", "error", "timeout"]:
|
284
286
|
break
|
285
287
|
|
286
288
|
def __run_non_streaming(self, request: RunAgentRequest) -> AgentOutput:
|
lmnr/sdk/decorators.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
from lmnr.opentelemetry_lib.decorators
|
1
|
+
from lmnr.opentelemetry_lib.decorators import (
|
2
2
|
entity_method,
|
3
3
|
aentity_method,
|
4
4
|
)
|
@@ -8,7 +8,9 @@ from typing import Callable, Literal, Optional, TypeVar, Union, cast
|
|
8
8
|
from typing_extensions import ParamSpec
|
9
9
|
|
10
10
|
from lmnr.opentelemetry_lib.tracing.attributes import SESSION_ID
|
11
|
-
from lmnr.opentelemetry_lib.tracing.
|
11
|
+
from lmnr.opentelemetry_lib.tracing.context_properties import (
|
12
|
+
update_association_properties,
|
13
|
+
)
|
12
14
|
|
13
15
|
from .utils import is_async
|
14
16
|
|
lmnr/sdk/evaluations.py
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
import asyncio
|
2
2
|
import re
|
3
3
|
import uuid
|
4
|
-
|
4
|
+
|
5
5
|
from tqdm import tqdm
|
6
6
|
from typing import Any, Awaitable, Optional, Set, Union
|
7
7
|
|
8
|
-
from lmnr.opentelemetry_lib.instruments import Instruments
|
8
|
+
from lmnr.opentelemetry_lib.tracing.instruments import Instruments
|
9
9
|
from lmnr.opentelemetry_lib.tracing.attributes import SPAN_TYPE
|
10
10
|
|
11
11
|
from lmnr.sdk.client.asynchronous.async_client import AsyncLaminarClient
|
@@ -111,7 +111,7 @@ class Evaluation:
|
|
111
111
|
trace_export_timeout_seconds: Optional[int] = None,
|
112
112
|
):
|
113
113
|
"""
|
114
|
-
Initializes an instance of the
|
114
|
+
Initializes an instance of the Evaluation class.
|
115
115
|
|
116
116
|
Parameters:
|
117
117
|
data (Union[List[EvaluationDatapoint|dict], EvaluationDataset]):\
|
lmnr/sdk/laminar.py
CHANGED
@@ -1,21 +1,17 @@
|
|
1
1
|
from contextlib import contextmanager
|
2
2
|
from contextvars import Context
|
3
3
|
from lmnr.opentelemetry_lib import TracerManager
|
4
|
-
from lmnr.opentelemetry_lib.instruments import Instruments
|
5
|
-
from lmnr.opentelemetry_lib.tracing import get_tracer
|
4
|
+
from lmnr.opentelemetry_lib.tracing.instruments import Instruments
|
5
|
+
from lmnr.opentelemetry_lib.tracing.tracer import get_tracer
|
6
6
|
from lmnr.opentelemetry_lib.tracing.attributes import (
|
7
7
|
ASSOCIATION_PROPERTIES,
|
8
8
|
Attributes,
|
9
9
|
SPAN_TYPE,
|
10
10
|
)
|
11
|
-
from lmnr.opentelemetry_lib
|
12
|
-
from lmnr.opentelemetry_lib.decorators
|
11
|
+
from lmnr.opentelemetry_lib import MAX_MANUAL_SPAN_PAYLOAD_SIZE
|
12
|
+
from lmnr.opentelemetry_lib.decorators import json_dumps
|
13
13
|
from opentelemetry import context as context_api, trace
|
14
14
|
from opentelemetry.context import attach, detach
|
15
|
-
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import (
|
16
|
-
OTLPSpanExporter,
|
17
|
-
Compression,
|
18
|
-
)
|
19
15
|
from opentelemetry.sdk.trace.id_generator import RandomIdGenerator
|
20
16
|
from opentelemetry.util.types import AttributeValue
|
21
17
|
|
@@ -34,7 +30,7 @@ from lmnr.opentelemetry_lib.tracing.attributes import (
|
|
34
30
|
SPAN_OUTPUT,
|
35
31
|
TRACE_TYPE,
|
36
32
|
)
|
37
|
-
from lmnr.opentelemetry_lib.tracing.
|
33
|
+
from lmnr.opentelemetry_lib.tracing.context_properties import (
|
38
34
|
get_association_properties,
|
39
35
|
remove_association_properties,
|
40
36
|
set_association_properties,
|
@@ -52,8 +48,6 @@ from .types import (
|
|
52
48
|
|
53
49
|
|
54
50
|
class Laminar:
|
55
|
-
__base_http_url: str
|
56
|
-
__base_grpc_url: str
|
57
51
|
__project_api_key: Optional[str] = None
|
58
52
|
__initialized: bool = False
|
59
53
|
|
@@ -65,9 +59,12 @@ class Laminar:
|
|
65
59
|
http_port: Optional[int] = None,
|
66
60
|
grpc_port: Optional[int] = None,
|
67
61
|
instruments: Optional[Set[Instruments]] = None,
|
62
|
+
disabled_instruments: Optional[Set[Instruments]] = None,
|
68
63
|
disable_batch: bool = False,
|
69
64
|
max_export_batch_size: Optional[int] = None,
|
70
65
|
export_timeout_seconds: Optional[int] = None,
|
66
|
+
set_global_tracer_provider: bool = True,
|
67
|
+
otel_logger_level: int = logging.ERROR,
|
71
68
|
):
|
72
69
|
"""Initialize Laminar context across the application.
|
73
70
|
This method must be called before using any other Laminar methods or
|
@@ -92,6 +89,8 @@ class Laminar:
|
|
92
89
|
enable. Defaults to all instruments. You can pass\
|
93
90
|
an empty set to disable all instruments. Read more:\
|
94
91
|
https://docs.lmnr.ai/tracing/automatic-instrumentation
|
92
|
+
disabled_instruments (Optional[Set[Instruments]], optional): Instruments to\
|
93
|
+
disable. Defaults to None.
|
95
94
|
disable_batch (bool, optional): If set to True, spans will be sent\
|
96
95
|
immediately to the backend. Useful for debugging, but\
|
97
96
|
may cause performance overhead in production.
|
@@ -100,6 +99,13 @@ class Laminar:
|
|
100
99
|
exporter. Defaults to 30 seconds (unlike the\
|
101
100
|
OpenTelemetry default of 10 seconds).
|
102
101
|
Defaults to None.
|
102
|
+
set_global_tracer_provider (bool, optional): If set to True, the\
|
103
|
+
Laminar tracer provider will be set as the global\
|
104
|
+
tracer provider. OpenTelemetry allows only one tracer\
|
105
|
+
provider per app, so set this to False, if you are using\
|
106
|
+
another tracing library. Setting this to False may break\
|
107
|
+
some external instrumentations, e.g. LiteLLM.
|
108
|
+
Defaults to True.
|
103
109
|
|
104
110
|
Raises:
|
105
111
|
ValueError: If project API key is not set
|
@@ -116,6 +122,8 @@ class Laminar:
|
|
116
122
|
|
117
123
|
url = base_url or from_env("LMNR_BASE_URL") or "https://api.lmnr.ai"
|
118
124
|
url = url.rstrip("/")
|
125
|
+
if not url.startswith("http"):
|
126
|
+
url = f"https://{url}"
|
119
127
|
if match := re.search(r":(\d{1,5})$", url):
|
120
128
|
url = url[: -len(match.group(0))]
|
121
129
|
if http_port is None:
|
@@ -124,36 +132,25 @@ class Laminar:
|
|
124
132
|
else:
|
125
133
|
cls.__logger.info(f"Using HTTP port passed as an argument: {http_port}")
|
126
134
|
|
127
|
-
cls.__base_http_url = f"{url}:{http_port or 443}"
|
128
|
-
cls.__base_grpc_url = f"{url}:{grpc_port or 8443}"
|
129
|
-
|
130
135
|
cls.__initialized = True
|
136
|
+
|
131
137
|
if not os.getenv("OTEL_ATTRIBUTE_COUNT_LIMIT"):
|
132
138
|
# each message is at least 2 attributes: role and content,
|
133
139
|
# but the default attribute limit is 128, so raise it
|
134
140
|
os.environ["OTEL_ATTRIBUTE_COUNT_LIMIT"] = "10000"
|
135
141
|
|
136
|
-
# if not is_latest_version():
|
137
|
-
# cls.__logger.warning(
|
138
|
-
# "You are using an older version of the Laminar SDK. "
|
139
|
-
# f"Latest version: {get_latest_pypi_version()}, current version: {SDK_VERSION}.\n"
|
140
|
-
# "Please update to the latest version by running "
|
141
|
-
# "`pip install --upgrade lmnr`."
|
142
|
-
# )
|
143
|
-
|
144
142
|
TracerManager.init(
|
145
|
-
|
143
|
+
base_url=url,
|
144
|
+
http_port=http_port or 443,
|
145
|
+
port=grpc_port or 8443,
|
146
146
|
project_api_key=cls.__project_api_key,
|
147
|
-
exporter=OTLPSpanExporter(
|
148
|
-
endpoint=cls.__base_grpc_url,
|
149
|
-
headers={"authorization": f"Bearer {cls.__project_api_key}"},
|
150
|
-
compression=Compression.Gzip,
|
151
|
-
# default timeout is 10 seconds, increase it to 30 seconds
|
152
|
-
timeout=export_timeout_seconds or 30,
|
153
|
-
),
|
154
147
|
instruments=instruments,
|
148
|
+
block_instruments=disabled_instruments,
|
155
149
|
disable_batch=disable_batch,
|
156
150
|
max_export_batch_size=max_export_batch_size,
|
151
|
+
timeout_seconds=export_timeout_seconds,
|
152
|
+
set_global_tracer_provider=set_global_tracer_provider,
|
153
|
+
otel_logger_level=otel_logger_level,
|
157
154
|
)
|
158
155
|
|
159
156
|
@classmethod
|
@@ -680,7 +677,7 @@ class Laminar:
|
|
680
677
|
"""Set the metadata for the current trace.
|
681
678
|
|
682
679
|
Args:
|
683
|
-
metadata (dict[str, str]): Metadata to set for the trace.
|
680
|
+
metadata (dict[str, str]): Metadata to set for the trace. Will be\
|
684
681
|
sent as attributes, so must be json serializable.
|
685
682
|
"""
|
686
683
|
props = {f"metadata.{k}": json_dumps(v) for k, v in metadata.items()}
|
lmnr/sdk/utils.py
CHANGED
@@ -37,10 +37,9 @@ def is_async(func: typing.Callable) -> bool:
|
|
37
37
|
return True
|
38
38
|
|
39
39
|
# Fallback: check if the function's code object contains 'async'.
|
40
|
-
# This is for cases when a decorator did not properly use
|
40
|
+
# This is for cases when a decorator (not ours) did not properly use
|
41
41
|
# `functools.wraps` or `functools.update_wrapper`
|
42
|
-
|
43
|
-
return (func.__code__.co_flags & CO_COROUTINE) != 0
|
42
|
+
return (func.__code__.co_flags & inspect.CO_COROUTINE) != 0
|
44
43
|
|
45
44
|
|
46
45
|
def is_async_iterator(o: typing.Any) -> bool:
|