lmnr 0.6.0__tar.gz → 0.6.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.
- {lmnr-0.6.0 → lmnr-0.6.1}/PKG-INFO +2 -1
- {lmnr-0.6.0 → lmnr-0.6.1}/pyproject.toml +4 -2
- {lmnr-0.6.0 → lmnr-0.6.1}/src/lmnr/opentelemetry_lib/__init__.py +7 -0
- {lmnr-0.6.0 → lmnr-0.6.1}/src/lmnr/opentelemetry_lib/tracing/__init__.py +22 -3
- {lmnr-0.6.0 → lmnr-0.6.1}/src/lmnr/sdk/browser/playwright_otel.py +22 -7
- {lmnr-0.6.0 → lmnr-0.6.1}/src/lmnr/sdk/browser/pw_utils.py +17 -5
- {lmnr-0.6.0 → lmnr-0.6.1}/src/lmnr/sdk/laminar.py +15 -0
- {lmnr-0.6.0 → lmnr-0.6.1}/src/lmnr/version.py +1 -1
- {lmnr-0.6.0 → lmnr-0.6.1}/LICENSE +0 -0
- {lmnr-0.6.0 → lmnr-0.6.1}/README.md +0 -0
- {lmnr-0.6.0 → lmnr-0.6.1}/src/lmnr/__init__.py +0 -0
- {lmnr-0.6.0 → lmnr-0.6.1}/src/lmnr/cli.py +0 -0
- {lmnr-0.6.0 → lmnr-0.6.1}/src/lmnr/opentelemetry_lib/.flake8 +0 -0
- {lmnr-0.6.0 → lmnr-0.6.1}/src/lmnr/opentelemetry_lib/decorators/__init__.py +0 -0
- {lmnr-0.6.0 → lmnr-0.6.1}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/google_genai/__init__.py +0 -0
- {lmnr-0.6.0 → lmnr-0.6.1}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/google_genai/config.py +0 -0
- {lmnr-0.6.0 → lmnr-0.6.1}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/google_genai/utils.py +0 -0
- {lmnr-0.6.0 → lmnr-0.6.1}/src/lmnr/opentelemetry_lib/tracing/_instrument_initializers.py +0 -0
- {lmnr-0.6.0 → lmnr-0.6.1}/src/lmnr/opentelemetry_lib/tracing/attributes.py +0 -0
- {lmnr-0.6.0 → lmnr-0.6.1}/src/lmnr/opentelemetry_lib/tracing/context_properties.py +0 -0
- {lmnr-0.6.0 → lmnr-0.6.1}/src/lmnr/opentelemetry_lib/tracing/exporter.py +0 -0
- {lmnr-0.6.0 → lmnr-0.6.1}/src/lmnr/opentelemetry_lib/tracing/instruments.py +0 -0
- {lmnr-0.6.0 → lmnr-0.6.1}/src/lmnr/opentelemetry_lib/tracing/processor.py +0 -0
- {lmnr-0.6.0 → lmnr-0.6.1}/src/lmnr/opentelemetry_lib/tracing/tracer.py +0 -0
- {lmnr-0.6.0 → lmnr-0.6.1}/src/lmnr/opentelemetry_lib/utils/__init__.py +0 -0
- {lmnr-0.6.0 → lmnr-0.6.1}/src/lmnr/opentelemetry_lib/utils/json_encoder.py +0 -0
- {lmnr-0.6.0 → lmnr-0.6.1}/src/lmnr/opentelemetry_lib/utils/package_check.py +0 -0
- {lmnr-0.6.0 → lmnr-0.6.1}/src/lmnr/py.typed +0 -0
- {lmnr-0.6.0 → lmnr-0.6.1}/src/lmnr/sdk/__init__.py +0 -0
- {lmnr-0.6.0 → lmnr-0.6.1}/src/lmnr/sdk/browser/__init__.py +0 -0
- {lmnr-0.6.0 → lmnr-0.6.1}/src/lmnr/sdk/browser/browser_use_otel.py +0 -0
- {lmnr-0.6.0 → lmnr-0.6.1}/src/lmnr/sdk/browser/patchright_otel.py +0 -0
- {lmnr-0.6.0 → lmnr-0.6.1}/src/lmnr/sdk/browser/rrweb/rrweb.umd.min.cjs +0 -0
- {lmnr-0.6.0 → lmnr-0.6.1}/src/lmnr/sdk/browser/utils.py +0 -0
- {lmnr-0.6.0 → lmnr-0.6.1}/src/lmnr/sdk/client/asynchronous/async_client.py +0 -0
- {lmnr-0.6.0 → lmnr-0.6.1}/src/lmnr/sdk/client/asynchronous/resources/__init__.py +0 -0
- {lmnr-0.6.0 → lmnr-0.6.1}/src/lmnr/sdk/client/asynchronous/resources/agent.py +0 -0
- {lmnr-0.6.0 → lmnr-0.6.1}/src/lmnr/sdk/client/asynchronous/resources/base.py +0 -0
- {lmnr-0.6.0 → lmnr-0.6.1}/src/lmnr/sdk/client/asynchronous/resources/browser_events.py +0 -0
- {lmnr-0.6.0 → lmnr-0.6.1}/src/lmnr/sdk/client/asynchronous/resources/evals.py +0 -0
- {lmnr-0.6.0 → lmnr-0.6.1}/src/lmnr/sdk/client/synchronous/resources/__init__.py +0 -0
- {lmnr-0.6.0 → lmnr-0.6.1}/src/lmnr/sdk/client/synchronous/resources/agent.py +0 -0
- {lmnr-0.6.0 → lmnr-0.6.1}/src/lmnr/sdk/client/synchronous/resources/base.py +0 -0
- {lmnr-0.6.0 → lmnr-0.6.1}/src/lmnr/sdk/client/synchronous/resources/browser_events.py +0 -0
- {lmnr-0.6.0 → lmnr-0.6.1}/src/lmnr/sdk/client/synchronous/resources/evals.py +0 -0
- {lmnr-0.6.0 → lmnr-0.6.1}/src/lmnr/sdk/client/synchronous/sync_client.py +0 -0
- {lmnr-0.6.0 → lmnr-0.6.1}/src/lmnr/sdk/datasets.py +0 -0
- {lmnr-0.6.0 → lmnr-0.6.1}/src/lmnr/sdk/decorators.py +0 -0
- {lmnr-0.6.0 → lmnr-0.6.1}/src/lmnr/sdk/eval_control.py +0 -0
- {lmnr-0.6.0 → lmnr-0.6.1}/src/lmnr/sdk/evaluations.py +0 -0
- {lmnr-0.6.0 → lmnr-0.6.1}/src/lmnr/sdk/log.py +0 -0
- {lmnr-0.6.0 → lmnr-0.6.1}/src/lmnr/sdk/types.py +0 -0
- {lmnr-0.6.0 → lmnr-0.6.1}/src/lmnr/sdk/utils.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: lmnr
|
3
|
-
Version: 0.6.
|
3
|
+
Version: 0.6.1
|
4
4
|
Summary: Python SDK for Laminar
|
5
5
|
License: Apache-2.0
|
6
6
|
Author: lmnr.ai
|
@@ -90,6 +90,7 @@ Requires-Dist: opentelemetry-instrumentation-replicate (>=0.40.5) ; extra == "al
|
|
90
90
|
Requires-Dist: opentelemetry-instrumentation-replicate (>=0.40.5) ; extra == "replicate"
|
91
91
|
Requires-Dist: opentelemetry-instrumentation-sagemaker (>=0.40.5) ; extra == "all"
|
92
92
|
Requires-Dist: opentelemetry-instrumentation-sagemaker (>=0.40.5) ; extra == "sagemaker"
|
93
|
+
Requires-Dist: opentelemetry-instrumentation-threading (>=0.54b0)
|
93
94
|
Requires-Dist: opentelemetry-instrumentation-together (>=0.40.5) ; extra == "all"
|
94
95
|
Requires-Dist: opentelemetry-instrumentation-together (>=0.40.5) ; extra == "together"
|
95
96
|
Requires-Dist: opentelemetry-instrumentation-transformers (>=0.40.5) ; extra == "all"
|
@@ -6,7 +6,7 @@
|
|
6
6
|
|
7
7
|
[project]
|
8
8
|
name = "lmnr"
|
9
|
-
version = "0.6.
|
9
|
+
version = "0.6.1"
|
10
10
|
description = "Python SDK for Laminar"
|
11
11
|
authors = [
|
12
12
|
{ name = "lmnr.ai", email = "founders@lmnr.ai" }
|
@@ -36,6 +36,7 @@ dependencies = [
|
|
36
36
|
# https://github.com/grpc/grpc/issues/38490
|
37
37
|
"grpcio<1.68.0",
|
38
38
|
"httpx>=0.25.0",
|
39
|
+
"opentelemetry-instrumentation-threading>=0.54b0",
|
39
40
|
]
|
40
41
|
|
41
42
|
[project.scripts]
|
@@ -117,10 +118,11 @@ dev = [
|
|
117
118
|
"pytest>=8.3.5",
|
118
119
|
"pytest-sugar>=1.0.0",
|
119
120
|
"pytest-asyncio>=0.26.0",
|
120
|
-
"playwright>=1.
|
121
|
+
"playwright>=1.52.0",
|
121
122
|
"vcrpy>=7.0.0",
|
122
123
|
"openai>=1.77.0",
|
123
124
|
"pytest-recording>=0.13.4",
|
125
|
+
"patchright>=1.52.3",
|
124
126
|
]
|
125
127
|
|
126
128
|
[build-system]
|
@@ -1,3 +1,4 @@
|
|
1
|
+
import logging
|
1
2
|
import sys
|
2
3
|
|
3
4
|
from typing import Optional, Set
|
@@ -20,6 +21,7 @@ class TracerManager:
|
|
20
21
|
exporter: Optional[SpanExporter] = None,
|
21
22
|
resource_attributes: dict = {},
|
22
23
|
instruments: Optional[Set[Instruments]] = None,
|
24
|
+
block_instruments: Optional[Set[Instruments]] = None,
|
23
25
|
base_url: str = "https://api.lmnr.ai",
|
24
26
|
port: int = 8443,
|
25
27
|
http_port: int = 443,
|
@@ -27,6 +29,8 @@ class TracerManager:
|
|
27
29
|
max_export_batch_size: Optional[int] = None,
|
28
30
|
force_http: bool = False,
|
29
31
|
timeout_seconds: int = 30,
|
32
|
+
set_global_tracer_provider: bool = True,
|
33
|
+
otel_logger_level: int = logging.ERROR,
|
30
34
|
) -> None:
|
31
35
|
enable_content_tracing = True
|
32
36
|
|
@@ -37,6 +41,7 @@ class TracerManager:
|
|
37
41
|
disable_batch=disable_batch,
|
38
42
|
exporter=exporter,
|
39
43
|
instruments=instruments,
|
44
|
+
block_instruments=block_instruments,
|
40
45
|
base_url=base_url,
|
41
46
|
port=port,
|
42
47
|
http_port=http_port,
|
@@ -44,6 +49,8 @@ class TracerManager:
|
|
44
49
|
max_export_batch_size=max_export_batch_size,
|
45
50
|
force_http=force_http,
|
46
51
|
timeout_seconds=timeout_seconds,
|
52
|
+
set_global_tracer_provider=set_global_tracer_provider,
|
53
|
+
otel_logger_level=otel_logger_level,
|
47
54
|
)
|
48
55
|
|
49
56
|
@staticmethod
|
@@ -11,13 +11,12 @@ from lmnr.opentelemetry_lib.tracing.instruments import (
|
|
11
11
|
)
|
12
12
|
|
13
13
|
from opentelemetry import trace
|
14
|
+
from opentelemetry.instrumentation.threading import ThreadingInstrumentor
|
14
15
|
from opentelemetry.sdk.resources import Resource
|
15
16
|
from opentelemetry.sdk.trace import TracerProvider, SpanProcessor
|
16
17
|
from opentelemetry.sdk.trace.export import SpanExporter
|
17
|
-
|
18
18
|
from typing import Optional, Set
|
19
19
|
|
20
|
-
|
21
20
|
module_logger = logging.getLogger(__name__)
|
22
21
|
console_log_handler = logging.StreamHandler()
|
23
22
|
console_log_handler.setFormatter(VerboseColorfulFormatter())
|
@@ -52,7 +51,12 @@ class TracerWrapper(object):
|
|
52
51
|
max_export_batch_size: Optional[int] = None,
|
53
52
|
force_http: bool = False,
|
54
53
|
timeout_seconds: int = 10,
|
54
|
+
set_global_tracer_provider: bool = True,
|
55
|
+
otel_logger_level: int = logging.ERROR,
|
55
56
|
) -> "TracerWrapper":
|
57
|
+
# Silence some opentelemetry warnings
|
58
|
+
logging.getLogger("opentelemetry.trace").setLevel(otel_logger_level)
|
59
|
+
|
56
60
|
base_http_url = f"{base_url}:{http_port}"
|
57
61
|
cls._initialize_logger(cls)
|
58
62
|
if not hasattr(cls, "instance"):
|
@@ -68,7 +72,6 @@ class TracerWrapper(object):
|
|
68
72
|
)
|
69
73
|
|
70
74
|
obj.__resource = Resource(attributes=TracerWrapper.resource_attributes)
|
71
|
-
obj.__tracer_provider = TracerProvider(resource=obj.__resource)
|
72
75
|
|
73
76
|
obj.__span_processor = LaminarSpanProcessor(
|
74
77
|
base_url=base_url,
|
@@ -81,8 +84,24 @@ class TracerWrapper(object):
|
|
81
84
|
disable_batch=disable_batch,
|
82
85
|
)
|
83
86
|
|
87
|
+
lmnr_provider = TracerProvider(resource=obj.__resource)
|
88
|
+
global_provider = trace.get_tracer_provider()
|
89
|
+
if set_global_tracer_provider and isinstance(
|
90
|
+
global_provider, trace.ProxyTracerProvider
|
91
|
+
):
|
92
|
+
trace.set_tracer_provider(lmnr_provider)
|
93
|
+
|
94
|
+
obj.__tracer_provider = lmnr_provider
|
95
|
+
|
84
96
|
obj.__tracer_provider.add_span_processor(obj.__span_processor)
|
85
97
|
|
98
|
+
# This is not a real instrumentation and does not generate telemetry
|
99
|
+
# data, but it is required to ensure that OpenTelemetry context
|
100
|
+
# propagation is enabled.
|
101
|
+
# See the README at:
|
102
|
+
# https://pypi.org/project/opentelemetry-instrumentation-threading/
|
103
|
+
ThreadingInstrumentor().instrument()
|
104
|
+
|
86
105
|
init_instrumentations(
|
87
106
|
tracer_provider=obj.__tracer_provider,
|
88
107
|
instruments=instruments,
|
@@ -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
|
@@ -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__)
|
@@ -59,9 +59,12 @@ class Laminar:
|
|
59
59
|
http_port: Optional[int] = None,
|
60
60
|
grpc_port: Optional[int] = None,
|
61
61
|
instruments: Optional[Set[Instruments]] = None,
|
62
|
+
disabled_instruments: Optional[Set[Instruments]] = None,
|
62
63
|
disable_batch: bool = False,
|
63
64
|
max_export_batch_size: Optional[int] = None,
|
64
65
|
export_timeout_seconds: Optional[int] = None,
|
66
|
+
set_global_tracer_provider: bool = True,
|
67
|
+
otel_logger_level: int = logging.ERROR,
|
65
68
|
):
|
66
69
|
"""Initialize Laminar context across the application.
|
67
70
|
This method must be called before using any other Laminar methods or
|
@@ -86,6 +89,8 @@ class Laminar:
|
|
86
89
|
enable. Defaults to all instruments. You can pass\
|
87
90
|
an empty set to disable all instruments. Read more:\
|
88
91
|
https://docs.lmnr.ai/tracing/automatic-instrumentation
|
92
|
+
disabled_instruments (Optional[Set[Instruments]], optional): Instruments to\
|
93
|
+
disable. Defaults to None.
|
89
94
|
disable_batch (bool, optional): If set to True, spans will be sent\
|
90
95
|
immediately to the backend. Useful for debugging, but\
|
91
96
|
may cause performance overhead in production.
|
@@ -94,6 +99,13 @@ class Laminar:
|
|
94
99
|
exporter. Defaults to 30 seconds (unlike the\
|
95
100
|
OpenTelemetry default of 10 seconds).
|
96
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.
|
97
109
|
|
98
110
|
Raises:
|
99
111
|
ValueError: If project API key is not set
|
@@ -133,9 +145,12 @@ class Laminar:
|
|
133
145
|
port=grpc_port or 8443,
|
134
146
|
project_api_key=cls.__project_api_key,
|
135
147
|
instruments=instruments,
|
148
|
+
block_instruments=disabled_instruments,
|
136
149
|
disable_batch=disable_batch,
|
137
150
|
max_export_batch_size=max_export_batch_size,
|
138
151
|
timeout_seconds=export_timeout_seconds,
|
152
|
+
set_global_tracer_provider=set_global_tracer_provider,
|
153
|
+
otel_logger_level=otel_logger_level,
|
139
154
|
)
|
140
155
|
|
141
156
|
@classmethod
|
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
|
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
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|