lmnr 0.4.64__tar.gz → 0.4.66__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.
Files changed (41) hide show
  1. {lmnr-0.4.64 → lmnr-0.4.66}/PKG-INFO +51 -51
  2. lmnr-0.4.66/pyproject.toml +122 -0
  3. {lmnr-0.4.64 → lmnr-0.4.66}/src/lmnr/openllmetry_sdk/instruments.py +1 -0
  4. {lmnr-0.4.64 → lmnr-0.4.66}/src/lmnr/openllmetry_sdk/tracing/tracing.py +50 -15
  5. lmnr-0.4.66/src/lmnr/sdk/browser/__init__.py +0 -0
  6. lmnr-0.4.66/src/lmnr/sdk/browser/browser_use_otel.py +117 -0
  7. lmnr-0.4.66/src/lmnr/sdk/browser/playwright_otel.py +310 -0
  8. lmnr-0.4.66/src/lmnr/sdk/browser/utils.py +104 -0
  9. lmnr-0.4.66/src/lmnr/sdk/client.py +313 -0
  10. {lmnr-0.4.64 → lmnr-0.4.66}/src/lmnr/sdk/datasets.py +2 -2
  11. {lmnr-0.4.64 → lmnr-0.4.66}/src/lmnr/sdk/evaluations.py +32 -10
  12. {lmnr-0.4.64 → lmnr-0.4.66}/src/lmnr/sdk/laminar.py +72 -194
  13. {lmnr-0.4.64 → lmnr-0.4.66}/src/lmnr/sdk/types.py +29 -4
  14. {lmnr-0.4.64 → lmnr-0.4.66}/src/lmnr/version.py +1 -1
  15. lmnr-0.4.64/pyproject.toml +0 -122
  16. lmnr-0.4.64/src/lmnr/sdk/browser/__init__.py +0 -9
  17. lmnr-0.4.64/src/lmnr/sdk/browser/playwright_patch.py +0 -377
  18. {lmnr-0.4.64 → lmnr-0.4.66}/LICENSE +0 -0
  19. {lmnr-0.4.64 → lmnr-0.4.66}/README.md +0 -0
  20. {lmnr-0.4.64 → lmnr-0.4.66}/src/lmnr/__init__.py +0 -0
  21. {lmnr-0.4.64 → lmnr-0.4.66}/src/lmnr/cli.py +0 -0
  22. {lmnr-0.4.64 → lmnr-0.4.66}/src/lmnr/openllmetry_sdk/.flake8 +0 -0
  23. {lmnr-0.4.64 → lmnr-0.4.66}/src/lmnr/openllmetry_sdk/__init__.py +0 -0
  24. {lmnr-0.4.64 → lmnr-0.4.66}/src/lmnr/openllmetry_sdk/config/__init__.py +0 -0
  25. {lmnr-0.4.64 → lmnr-0.4.66}/src/lmnr/openllmetry_sdk/decorators/__init__.py +0 -0
  26. {lmnr-0.4.64 → lmnr-0.4.66}/src/lmnr/openllmetry_sdk/decorators/base.py +0 -0
  27. {lmnr-0.4.64 → lmnr-0.4.66}/src/lmnr/openllmetry_sdk/tracing/__init__.py +0 -0
  28. {lmnr-0.4.64 → lmnr-0.4.66}/src/lmnr/openllmetry_sdk/tracing/attributes.py +0 -0
  29. {lmnr-0.4.64 → lmnr-0.4.66}/src/lmnr/openllmetry_sdk/tracing/content_allow_list.py +0 -0
  30. {lmnr-0.4.64 → lmnr-0.4.66}/src/lmnr/openllmetry_sdk/tracing/context_manager.py +0 -0
  31. {lmnr-0.4.64 → lmnr-0.4.66}/src/lmnr/openllmetry_sdk/utils/__init__.py +0 -0
  32. {lmnr-0.4.64 → lmnr-0.4.66}/src/lmnr/openllmetry_sdk/utils/in_memory_span_exporter.py +0 -0
  33. {lmnr-0.4.64 → lmnr-0.4.66}/src/lmnr/openllmetry_sdk/utils/json_encoder.py +0 -0
  34. {lmnr-0.4.64 → lmnr-0.4.66}/src/lmnr/openllmetry_sdk/utils/package_check.py +0 -0
  35. {lmnr-0.4.64 → lmnr-0.4.66}/src/lmnr/py.typed +0 -0
  36. {lmnr-0.4.64 → lmnr-0.4.66}/src/lmnr/sdk/__init__.py +0 -0
  37. {lmnr-0.4.64 → lmnr-0.4.66}/src/lmnr/sdk/browser/rrweb/rrweb.min.js +0 -0
  38. {lmnr-0.4.64 → lmnr-0.4.66}/src/lmnr/sdk/decorators.py +0 -0
  39. {lmnr-0.4.64 → lmnr-0.4.66}/src/lmnr/sdk/eval_control.py +0 -0
  40. {lmnr-0.4.64 → lmnr-0.4.66}/src/lmnr/sdk/log.py +0 -0
  41. {lmnr-0.4.64 → lmnr-0.4.66}/src/lmnr/sdk/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: lmnr
3
- Version: 0.4.64
3
+ Version: 0.4.66
4
4
  Summary: Python SDK for Laminar
5
5
  License: Apache-2.0
6
6
  Author: lmnr.ai
@@ -45,60 +45,60 @@ Requires-Dist: grpcio (<1.68.0)
45
45
  Requires-Dist: opentelemetry-api (>=1.28.0)
46
46
  Requires-Dist: opentelemetry-exporter-otlp-proto-grpc (>=1.28.0)
47
47
  Requires-Dist: opentelemetry-exporter-otlp-proto-http (>=1.28.0)
48
- Requires-Dist: opentelemetry-instrumentation-alephalpha (>=0.37.1) ; extra == "alephalpha"
49
- Requires-Dist: opentelemetry-instrumentation-alephalpha (>=0.37.1) ; extra == "all"
50
- Requires-Dist: opentelemetry-instrumentation-anthropic (>=0.37.1) ; extra == "all"
51
- Requires-Dist: opentelemetry-instrumentation-anthropic (>=0.37.1) ; extra == "anthropic"
52
- Requires-Dist: opentelemetry-instrumentation-bedrock (>=0.37.1) ; extra == "all"
53
- Requires-Dist: opentelemetry-instrumentation-bedrock (>=0.37.1) ; extra == "bedrock"
54
- Requires-Dist: opentelemetry-instrumentation-chromadb (>=0.37.1) ; extra == "all"
55
- Requires-Dist: opentelemetry-instrumentation-chromadb (>=0.37.1) ; extra == "chromadb"
56
- Requires-Dist: opentelemetry-instrumentation-cohere (>=0.37.1) ; extra == "all"
57
- Requires-Dist: opentelemetry-instrumentation-cohere (>=0.37.1) ; extra == "cohere"
58
- Requires-Dist: opentelemetry-instrumentation-google-generativeai (>=0.37.1) ; extra == "all"
59
- Requires-Dist: opentelemetry-instrumentation-google-generativeai (>=0.37.1) ; extra == "google-generativeai"
60
- Requires-Dist: opentelemetry-instrumentation-groq (>=0.37.1) ; extra == "all"
61
- Requires-Dist: opentelemetry-instrumentation-groq (>=0.37.1) ; extra == "groq"
62
- Requires-Dist: opentelemetry-instrumentation-haystack (>=0.37.1) ; extra == "all"
63
- Requires-Dist: opentelemetry-instrumentation-haystack (>=0.37.1) ; extra == "haystack"
64
- Requires-Dist: opentelemetry-instrumentation-lancedb (>=0.37.1) ; extra == "all"
65
- Requires-Dist: opentelemetry-instrumentation-lancedb (>=0.37.1) ; extra == "lancedb"
66
- Requires-Dist: opentelemetry-instrumentation-langchain (>=0.37.1) ; extra == "all"
67
- Requires-Dist: opentelemetry-instrumentation-langchain (>=0.37.1) ; extra == "langchain"
68
- Requires-Dist: opentelemetry-instrumentation-llamaindex (>=0.37.1) ; extra == "all"
69
- Requires-Dist: opentelemetry-instrumentation-llamaindex (>=0.37.1) ; extra == "llamaindex"
70
- Requires-Dist: opentelemetry-instrumentation-marqo (>=0.37.1) ; extra == "all"
71
- Requires-Dist: opentelemetry-instrumentation-marqo (>=0.37.1) ; extra == "marqo"
72
- Requires-Dist: opentelemetry-instrumentation-milvus (>=0.37.1) ; extra == "all"
73
- Requires-Dist: opentelemetry-instrumentation-milvus (>=0.37.1) ; extra == "milvus"
74
- Requires-Dist: opentelemetry-instrumentation-mistralai (>=0.37.1) ; extra == "all"
75
- Requires-Dist: opentelemetry-instrumentation-mistralai (>=0.37.1) ; extra == "mistralai"
76
- Requires-Dist: opentelemetry-instrumentation-ollama (>=0.37.1) ; extra == "all"
77
- Requires-Dist: opentelemetry-instrumentation-ollama (>=0.37.1) ; extra == "ollama"
78
- Requires-Dist: opentelemetry-instrumentation-openai (>=0.37.1) ; extra == "all"
79
- Requires-Dist: opentelemetry-instrumentation-openai (>=0.37.1) ; extra == "openai"
80
- Requires-Dist: opentelemetry-instrumentation-pinecone (>=0.37.1) ; extra == "all"
81
- Requires-Dist: opentelemetry-instrumentation-pinecone (>=0.37.1) ; extra == "pinecone"
82
- Requires-Dist: opentelemetry-instrumentation-qdrant (>=0.37.1) ; extra == "all"
83
- Requires-Dist: opentelemetry-instrumentation-qdrant (>=0.37.1) ; extra == "qdrant"
84
- Requires-Dist: opentelemetry-instrumentation-replicate (>=0.37.1) ; extra == "all"
85
- Requires-Dist: opentelemetry-instrumentation-replicate (>=0.37.1) ; extra == "replicate"
48
+ Requires-Dist: opentelemetry-instrumentation-alephalpha (>=0.38.12) ; extra == "alephalpha"
49
+ Requires-Dist: opentelemetry-instrumentation-alephalpha (>=0.38.12) ; extra == "all"
50
+ Requires-Dist: opentelemetry-instrumentation-anthropic (>=0.38.12) ; extra == "all"
51
+ Requires-Dist: opentelemetry-instrumentation-anthropic (>=0.38.12) ; extra == "anthropic"
52
+ Requires-Dist: opentelemetry-instrumentation-bedrock (>=0.38.12) ; extra == "all"
53
+ Requires-Dist: opentelemetry-instrumentation-bedrock (>=0.38.12) ; extra == "bedrock"
54
+ Requires-Dist: opentelemetry-instrumentation-chromadb (>=0.38.12) ; extra == "all"
55
+ Requires-Dist: opentelemetry-instrumentation-chromadb (>=0.38.12) ; extra == "chromadb"
56
+ Requires-Dist: opentelemetry-instrumentation-cohere (>=0.38.12) ; extra == "all"
57
+ Requires-Dist: opentelemetry-instrumentation-cohere (>=0.38.12) ; extra == "cohere"
58
+ Requires-Dist: opentelemetry-instrumentation-google-generativeai (>=0.38.12) ; extra == "all"
59
+ Requires-Dist: opentelemetry-instrumentation-google-generativeai (>=0.38.12) ; extra == "google-generativeai"
60
+ Requires-Dist: opentelemetry-instrumentation-groq (>=0.38.12) ; extra == "all"
61
+ Requires-Dist: opentelemetry-instrumentation-groq (>=0.38.12) ; extra == "groq"
62
+ Requires-Dist: opentelemetry-instrumentation-haystack (>=0.38.12) ; extra == "all"
63
+ Requires-Dist: opentelemetry-instrumentation-haystack (>=0.38.12) ; extra == "haystack"
64
+ Requires-Dist: opentelemetry-instrumentation-lancedb (>=0.38.12) ; extra == "all"
65
+ Requires-Dist: opentelemetry-instrumentation-lancedb (>=0.38.12) ; extra == "lancedb"
66
+ Requires-Dist: opentelemetry-instrumentation-langchain (>=0.38.12) ; extra == "all"
67
+ Requires-Dist: opentelemetry-instrumentation-langchain (>=0.38.12) ; extra == "langchain"
68
+ Requires-Dist: opentelemetry-instrumentation-llamaindex (>=0.38.12) ; extra == "all"
69
+ Requires-Dist: opentelemetry-instrumentation-llamaindex (>=0.38.12) ; extra == "llamaindex"
70
+ Requires-Dist: opentelemetry-instrumentation-marqo (>=0.38.12) ; extra == "all"
71
+ Requires-Dist: opentelemetry-instrumentation-marqo (>=0.38.12) ; extra == "marqo"
72
+ Requires-Dist: opentelemetry-instrumentation-milvus (>=0.38.12) ; extra == "all"
73
+ Requires-Dist: opentelemetry-instrumentation-milvus (>=0.38.12) ; extra == "milvus"
74
+ Requires-Dist: opentelemetry-instrumentation-mistralai (>=0.38.12) ; extra == "all"
75
+ Requires-Dist: opentelemetry-instrumentation-mistralai (>=0.38.12) ; extra == "mistralai"
76
+ Requires-Dist: opentelemetry-instrumentation-ollama (>=0.38.12) ; extra == "all"
77
+ Requires-Dist: opentelemetry-instrumentation-ollama (>=0.38.12) ; extra == "ollama"
78
+ Requires-Dist: opentelemetry-instrumentation-openai (>=0.38.12) ; extra == "all"
79
+ Requires-Dist: opentelemetry-instrumentation-openai (>=0.38.12) ; extra == "openai"
80
+ Requires-Dist: opentelemetry-instrumentation-pinecone (>=0.38.12) ; extra == "all"
81
+ Requires-Dist: opentelemetry-instrumentation-pinecone (>=0.38.12) ; extra == "pinecone"
82
+ Requires-Dist: opentelemetry-instrumentation-qdrant (>=0.38.12) ; extra == "all"
83
+ Requires-Dist: opentelemetry-instrumentation-qdrant (>=0.38.12) ; extra == "qdrant"
84
+ Requires-Dist: opentelemetry-instrumentation-replicate (>=0.38.12) ; extra == "all"
85
+ Requires-Dist: opentelemetry-instrumentation-replicate (>=0.38.12) ; extra == "replicate"
86
86
  Requires-Dist: opentelemetry-instrumentation-requests (>=0.50b0)
87
- Requires-Dist: opentelemetry-instrumentation-sagemaker (>=0.37.1) ; extra == "all"
88
- Requires-Dist: opentelemetry-instrumentation-sagemaker (>=0.37.1) ; extra == "sagemaker"
87
+ Requires-Dist: opentelemetry-instrumentation-sagemaker (>=0.38.12) ; extra == "all"
88
+ Requires-Dist: opentelemetry-instrumentation-sagemaker (>=0.38.12) ; extra == "sagemaker"
89
89
  Requires-Dist: opentelemetry-instrumentation-sqlalchemy (>=0.50b0)
90
90
  Requires-Dist: opentelemetry-instrumentation-threading (>=0.50b0)
91
- Requires-Dist: opentelemetry-instrumentation-together (>=0.37.1) ; extra == "all"
92
- Requires-Dist: opentelemetry-instrumentation-together (>=0.37.1) ; extra == "together"
93
- Requires-Dist: opentelemetry-instrumentation-transformers (>=0.37.1) ; extra == "all"
94
- Requires-Dist: opentelemetry-instrumentation-transformers (>=0.37.1) ; extra == "transformers"
91
+ Requires-Dist: opentelemetry-instrumentation-together (>=0.38.12) ; extra == "all"
92
+ Requires-Dist: opentelemetry-instrumentation-together (>=0.38.12) ; extra == "together"
93
+ Requires-Dist: opentelemetry-instrumentation-transformers (>=0.38.12) ; extra == "all"
94
+ Requires-Dist: opentelemetry-instrumentation-transformers (>=0.38.12) ; extra == "transformers"
95
95
  Requires-Dist: opentelemetry-instrumentation-urllib3 (>=0.50b0)
96
- Requires-Dist: opentelemetry-instrumentation-vertexai (>=0.37.1) ; extra == "all"
97
- Requires-Dist: opentelemetry-instrumentation-vertexai (>=0.37.1) ; extra == "vertexai"
98
- Requires-Dist: opentelemetry-instrumentation-watsonx (>=0.37.1) ; extra == "all"
99
- Requires-Dist: opentelemetry-instrumentation-watsonx (>=0.37.1) ; extra == "watsonx"
100
- Requires-Dist: opentelemetry-instrumentation-weaviate (>=0.37.1) ; extra == "all"
101
- Requires-Dist: opentelemetry-instrumentation-weaviate (>=0.37.1) ; extra == "weaviate"
96
+ Requires-Dist: opentelemetry-instrumentation-vertexai (>=0.38.12) ; extra == "all"
97
+ Requires-Dist: opentelemetry-instrumentation-vertexai (>=0.38.12) ; extra == "vertexai"
98
+ Requires-Dist: opentelemetry-instrumentation-watsonx (>=0.38.12) ; extra == "all"
99
+ Requires-Dist: opentelemetry-instrumentation-watsonx (>=0.38.12) ; extra == "watsonx"
100
+ Requires-Dist: opentelemetry-instrumentation-weaviate (>=0.38.12) ; extra == "all"
101
+ Requires-Dist: opentelemetry-instrumentation-weaviate (>=0.38.12) ; extra == "weaviate"
102
102
  Requires-Dist: opentelemetry-sdk (>=1.28.0)
103
103
  Requires-Dist: opentelemetry-semantic-conventions-ai (>=0.4.2)
104
104
  Requires-Dist: pydantic (>=2.0.3)
@@ -0,0 +1,122 @@
1
+ # Laminar Python
2
+
3
+ # If you are looking for information about possible extras installations,
4
+ # i.e. what you can pass into `pip install 'lmnr[extra1,extra2]'`, please see the
5
+ # `[project.optional-dependencies]` section below.
6
+
7
+ [project]
8
+ name = "lmnr"
9
+ version = "0.4.66"
10
+ description = "Python SDK for Laminar"
11
+ authors = [
12
+ { name = "lmnr.ai", email = "founders@lmnr.ai" }
13
+ ]
14
+ readme = "README.md"
15
+ requires-python = ">=3.9,<4"
16
+ license = "Apache-2.0"
17
+ dependencies = [
18
+ "pydantic (>=2.0.3)",
19
+ "requests (>=2.0)",
20
+ "python-dotenv (>=1.0)",
21
+ "opentelemetry-api (>=1.28.0)",
22
+ "opentelemetry-sdk (>=1.28.0)",
23
+ "opentelemetry-exporter-otlp-proto-http (>=1.28.0)",
24
+ "opentelemetry-exporter-otlp-proto-grpc (>=1.28.0)",
25
+ "opentelemetry-instrumentation-requests (>=0.50b0)",
26
+ "opentelemetry-instrumentation-sqlalchemy (>=0.50b0)",
27
+ "opentelemetry-instrumentation-urllib3 (>=0.50b0)",
28
+ "opentelemetry-instrumentation-threading (>=0.50b0)",
29
+ "opentelemetry-semantic-conventions-ai (>=0.4.2)",
30
+ "tqdm (>=4.0)",
31
+ "argparse (>=1.0)",
32
+ "aiohttp (>=3.0)",
33
+ "tenacity (>=8.0)",
34
+ # explicitly freeze grpcio. Since 1.68.0, grpcio writes a warning message
35
+ # that looks scary, but is harmless.
36
+ # WARNING: All log messages before absl::InitializeLog() is called are written to STDERR
37
+ # E0000 00:00:1737439981.199902 9456033 init.cc:229] grpc_wait_for_shutdown_with_timeout() timed out.
38
+ #
39
+ # Related issue:
40
+ # https://discuss.ai.google.dev/t/warning-all-log-messages-before-absl-initializelog-is-called-are-written-to-stderr-e0000-001731955515-629532-17124-init-cc-229-grpc-wait-for-shutdown-with-timeout-timed-out/50020
41
+ # https://github.com/grpc/grpc/issues/38490
42
+ "grpcio<1.68.0",
43
+ ]
44
+
45
+ [project.scripts]
46
+ lmnr = "lmnr.cli:cli"
47
+
48
+ [project.optional-dependencies]
49
+ # List of all possible extras. You can specify one or more of these extras
50
+ # when installing the package, using any of the following examples:
51
+ # `pip install 'lmnr[anthropic,openai]'`
52
+ # `uv pip install 'lmnr[anthropic,openai]'`
53
+ # `uv add lmnr --extra anthropic --extra openai`
54
+ # `poetry add 'lmnr[anthropic,openai]'`
55
+
56
+ alephalpha=["opentelemetry-instrumentation-alephalpha>=0.38.12"]
57
+ anthropic=["opentelemetry-instrumentation-anthropic>=0.38.12"]
58
+ bedrock=["opentelemetry-instrumentation-bedrock>=0.38.12"]
59
+ chromadb=["opentelemetry-instrumentation-chromadb>=0.38.12"]
60
+ cohere=["opentelemetry-instrumentation-cohere>=0.38.12"]
61
+ google-generativeai=["opentelemetry-instrumentation-google-generativeai>=0.38.12"]
62
+ groq=["opentelemetry-instrumentation-groq>=0.38.12"]
63
+ haystack=["opentelemetry-instrumentation-haystack>=0.38.12"]
64
+ lancedb=["opentelemetry-instrumentation-lancedb>=0.38.12"]
65
+ langchain=["opentelemetry-instrumentation-langchain>=0.38.12"]
66
+ llamaindex=["opentelemetry-instrumentation-llamaindex>=0.38.12"]
67
+ marqo=["opentelemetry-instrumentation-marqo>=0.38.12"]
68
+ milvus=["opentelemetry-instrumentation-milvus>=0.38.12"]
69
+ mistralai=["opentelemetry-instrumentation-mistralai>=0.38.12"]
70
+ ollama=["opentelemetry-instrumentation-ollama>=0.38.12"]
71
+ openai=["opentelemetry-instrumentation-openai>=0.38.12"]
72
+ pinecone=["opentelemetry-instrumentation-pinecone>=0.38.12"]
73
+ qdrant=["opentelemetry-instrumentation-qdrant>=0.38.12"]
74
+ replicate=["opentelemetry-instrumentation-replicate>=0.38.12"]
75
+ sagemaker=["opentelemetry-instrumentation-sagemaker>=0.38.12"]
76
+ together=["opentelemetry-instrumentation-together>=0.38.12"]
77
+ transformers=["opentelemetry-instrumentation-transformers>=0.38.12"]
78
+ vertexai=["opentelemetry-instrumentation-vertexai>=0.38.12"]
79
+ watsonx=["opentelemetry-instrumentation-watsonx>=0.38.12"]
80
+ weaviate=["opentelemetry-instrumentation-weaviate>=0.38.12"]
81
+ # `all` is the group added for convenience, if you want to install all
82
+ # the instrumentations.
83
+ all = [
84
+ "opentelemetry-instrumentation-alephalpha>=0.38.12",
85
+ "opentelemetry-instrumentation-anthropic>=0.38.12",
86
+ "opentelemetry-instrumentation-bedrock>=0.38.12",
87
+ "opentelemetry-instrumentation-chromadb>=0.38.12",
88
+ "opentelemetry-instrumentation-cohere>=0.38.12",
89
+ "opentelemetry-instrumentation-google-generativeai>=0.38.12",
90
+ "opentelemetry-instrumentation-groq>=0.38.12",
91
+ "opentelemetry-instrumentation-haystack>=0.38.12",
92
+ "opentelemetry-instrumentation-lancedb>=0.38.12",
93
+ "opentelemetry-instrumentation-langchain>=0.38.12",
94
+ "opentelemetry-instrumentation-llamaindex>=0.38.12",
95
+ "opentelemetry-instrumentation-marqo>=0.38.12",
96
+ "opentelemetry-instrumentation-milvus>=0.38.12",
97
+ "opentelemetry-instrumentation-mistralai>=0.38.12",
98
+ "opentelemetry-instrumentation-ollama>=0.38.12",
99
+ "opentelemetry-instrumentation-openai>=0.38.12",
100
+ "opentelemetry-instrumentation-pinecone>=0.38.12",
101
+ "opentelemetry-instrumentation-qdrant>=0.38.12",
102
+ "opentelemetry-instrumentation-replicate>=0.38.12",
103
+ "opentelemetry-instrumentation-sagemaker>=0.38.12",
104
+ "opentelemetry-instrumentation-together>=0.38.12",
105
+ "opentelemetry-instrumentation-transformers>=0.38.12",
106
+ "opentelemetry-instrumentation-vertexai>=0.38.12",
107
+ "opentelemetry-instrumentation-watsonx>=0.38.12",
108
+ "opentelemetry-instrumentation-weaviate>=0.38.12"
109
+ ]
110
+
111
+ [dependency-groups]
112
+ dev = [
113
+ "autopep8",
114
+ "flake8",
115
+ "pytest>=8.3.4",
116
+ "pytest-sugar",
117
+ "pytest-asyncio>=0.25.2"
118
+ ]
119
+
120
+ [build-system]
121
+ requires = ["poetry-core"]
122
+ build-backend = "poetry.core.masonry.api"
@@ -7,6 +7,7 @@ class Instruments(Enum):
7
7
  ALEPHALPHA = "alephalpha"
8
8
  ANTHROPIC = "anthropic"
9
9
  BEDROCK = "bedrock"
10
+ BROWSER_USE = "browser_use"
10
11
  CHROMA = "chroma"
11
12
  COHERE = "cohere"
12
13
  GOOGLE_GENERATIVEAI = "google_generativeai"
@@ -6,7 +6,6 @@ import uuid
6
6
  from contextvars import Context
7
7
  from lmnr.sdk.log import VerboseColorfulFormatter
8
8
  from lmnr.openllmetry_sdk.instruments import Instruments
9
- from lmnr.sdk.browser import init_browser_tracing
10
9
  from lmnr.openllmetry_sdk.tracing.attributes import (
11
10
  ASSOCIATION_PROPERTIES,
12
11
  SPAN_IDS_PATH,
@@ -28,7 +27,7 @@ from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import (
28
27
  )
29
28
  from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import Compression
30
29
  from opentelemetry.instrumentation.threading import ThreadingInstrumentor
31
- from opentelemetry.context import get_value, attach, get_current, set_value, Context
30
+ from opentelemetry.context import get_value, attach, get_current, set_value
32
31
  from opentelemetry.propagate import set_global_textmap
33
32
  from opentelemetry.propagators.textmap import TextMapPropagator
34
33
  from opentelemetry.sdk.resources import Resource
@@ -38,7 +37,7 @@ from opentelemetry.sdk.trace.export import (
38
37
  SimpleSpanProcessor,
39
38
  BatchSpanProcessor,
40
39
  )
41
- from opentelemetry.sdk.trace import SpanLimits
40
+ from opentelemetry.trace import get_tracer_provider, ProxyTracerProvider
42
41
 
43
42
  from typing import Dict, Optional, Set
44
43
 
@@ -238,6 +237,10 @@ def set_association_properties(properties: dict) -> None:
238
237
  _set_association_properties_attributes(span, properties)
239
238
 
240
239
 
240
+ def get_association_properties(context: Optional[Context] = None) -> dict:
241
+ return get_value("association_properties", context) or {}
242
+
243
+
241
244
  def update_association_properties(
242
245
  properties: dict,
243
246
  set_on_current_span: bool = True,
@@ -296,18 +299,21 @@ def init_spans_exporter(api_endpoint: str, headers: Dict[str, str]) -> SpanExpor
296
299
  # TODO: check if it's safer to use the default tracer provider obtained from
297
300
  # get_tracer_provider()
298
301
  def init_tracer_provider(resource: Resource) -> TracerProvider:
299
- tracer_provider = TracerProvider(
300
- resource=resource,
301
- span_limits=SpanLimits(
302
- # this defaults to 128, which causes us to drop messages
303
- max_attributes=MAX_EVENTS_OR_ATTRIBUTES_PER_SPAN,
304
- max_span_attributes=MAX_EVENTS_OR_ATTRIBUTES_PER_SPAN,
305
- max_event_attributes=MAX_EVENTS_OR_ATTRIBUTES_PER_SPAN,
306
- max_events=MAX_EVENTS_OR_ATTRIBUTES_PER_SPAN,
307
- ),
308
- )
302
+ provider: TracerProvider = None
303
+ default_provider: TracerProvider = get_tracer_provider()
304
+
305
+ if isinstance(default_provider, ProxyTracerProvider):
306
+ provider = TracerProvider(resource=resource)
307
+ trace.set_tracer_provider(provider)
308
+ elif not hasattr(default_provider, "add_span_processor"):
309
+ module_logger.error(
310
+ "Cannot add span processor to the default provider since it doesn't support it"
311
+ )
312
+ return
313
+ else:
314
+ provider = default_provider
309
315
 
310
- return tracer_provider
316
+ return provider
311
317
 
312
318
 
313
319
  def init_instrumentations(
@@ -428,7 +434,10 @@ def init_instrumentations(
428
434
  if init_weaviate_instrumentor():
429
435
  instrument_set = True
430
436
  elif instrument == Instruments.PLAYWRIGHT:
431
- if init_browser_tracing(base_http_url, project_api_key):
437
+ if init_playwright_instrumentor():
438
+ instrument_set = True
439
+ elif instrument == Instruments.BROWSER_USE:
440
+ if init_browser_use_instrumentor():
432
441
  instrument_set = True
433
442
  else:
434
443
  module_logger.warning(
@@ -443,6 +452,32 @@ def init_instrumentations(
443
452
  return instrument_set
444
453
 
445
454
 
455
+ def init_browser_use_instrumentor():
456
+ try:
457
+ if is_package_installed("browser-use"):
458
+ from lmnr.sdk.browser.browser_use_otel import BrowserUseInstrumentor
459
+
460
+ instrumentor = BrowserUseInstrumentor()
461
+ instrumentor.instrument()
462
+ return True
463
+ except Exception as e:
464
+ module_logger.error(f"Error initializing BrowserUse instrumentor: {e}")
465
+ return False
466
+
467
+
468
+ def init_playwright_instrumentor():
469
+ try:
470
+ if is_package_installed("playwright"):
471
+ from lmnr.sdk.browser.playwright_otel import PlaywrightInstrumentor
472
+
473
+ instrumentor = PlaywrightInstrumentor()
474
+ instrumentor.instrument()
475
+ return True
476
+ except Exception as e:
477
+ module_logger.error(f"Error initializing Playwright instrumentor: {e}")
478
+ return False
479
+
480
+
446
481
  def init_openai_instrumentor(should_enrich_metrics: bool):
447
482
  try:
448
483
  if is_package_installed("openai") and is_package_installed(
File without changes
@@ -0,0 +1,117 @@
1
+ from lmnr.openllmetry_sdk.decorators.base import json_dumps
2
+ from lmnr.sdk.browser.utils import _with_tracer_wrapper
3
+ from lmnr.sdk.utils import get_input_from_func_args
4
+ from lmnr.version import SDK_VERSION
5
+
6
+ from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
7
+ from opentelemetry.instrumentation.utils import unwrap
8
+ from opentelemetry.trace import get_tracer, Tracer
9
+ from typing import Collection
10
+ from wrapt import wrap_function_wrapper
11
+
12
+ _instruments = ("browser-use >= 0.1.0",)
13
+
14
+ WRAPPED_METHODS = [
15
+ {
16
+ "package": "browser_use.agent.service",
17
+ "object": "Agent",
18
+ "method": "run",
19
+ "span_name": "agent.run",
20
+ "ignore_input": False,
21
+ "ignore_output": True,
22
+ "span_type": "DEFAULT",
23
+ },
24
+ {
25
+ "package": "browser_use.agent.service",
26
+ "object": "Agent",
27
+ "method": "step",
28
+ "span_name": "agent.step",
29
+ "ignore_input": True,
30
+ "ignore_output": True,
31
+ "span_type": "DEFAULT",
32
+ },
33
+ {
34
+ "package": "browser_use.controller.service",
35
+ "object": "Controller",
36
+ "method": "act",
37
+ "span_name": "controller.act",
38
+ "ignore_input": True,
39
+ "ignore_output": False,
40
+ "span_type": "DEFAULT",
41
+ },
42
+ {
43
+ "package": "browser_use.controller.registry.service",
44
+ "object": "Registry",
45
+ "method": "execute_action",
46
+ "ignore_input": False,
47
+ "ignore_output": False,
48
+ "span_type": "TOOL",
49
+ },
50
+ ]
51
+
52
+
53
+ @_with_tracer_wrapper
54
+ async def _wrap(tracer: Tracer, to_wrap, wrapped, instance, args, kwargs):
55
+ span_name = to_wrap.get("span_name")
56
+ attributes = {
57
+ "lmnr.span.type": to_wrap.get("span_type"),
58
+ }
59
+ if to_wrap.get("method") == "execute_action":
60
+ span_name = args[0] if len(args) > 0 else kwargs.get("action_name", "action")
61
+ attributes["lmnr.span.input"] = json_dumps(
62
+ {
63
+ "action": span_name,
64
+ "params": args[1] if len(args) > 1 else kwargs.get("params", {}),
65
+ }
66
+ )
67
+ else:
68
+ if not to_wrap.get("ignore_input"):
69
+ attributes["lmnr.span.input"] = json_dumps(
70
+ get_input_from_func_args(wrapped, True, args, kwargs)
71
+ )
72
+ with tracer.start_as_current_span(span_name, attributes=attributes) as span:
73
+ span.set_attributes(attributes)
74
+ result = await wrapped(*args, **kwargs)
75
+ if not to_wrap.get("ignore_output"):
76
+ span.set_attribute("lmnr.span.output", json_dumps(result))
77
+ return result
78
+
79
+
80
+ class BrowserUseInstrumentor(BaseInstrumentor):
81
+ def __init__(self):
82
+ super().__init__()
83
+
84
+ def instrumentation_dependencies(self) -> Collection[str]:
85
+ return _instruments
86
+
87
+ def _instrument(self, **kwargs):
88
+ tracer_provider = kwargs.get("tracer_provider")
89
+ tracer = get_tracer(__name__, SDK_VERSION, tracer_provider)
90
+
91
+ for wrapped_method in WRAPPED_METHODS:
92
+ wrap_package = wrapped_method.get("package")
93
+ wrap_object = wrapped_method.get("object")
94
+ wrap_method = wrapped_method.get("method")
95
+
96
+ try:
97
+ wrap_function_wrapper(
98
+ wrap_package,
99
+ f"{wrap_object}.{wrap_method}",
100
+ _wrap(
101
+ tracer,
102
+ wrapped_method,
103
+ ),
104
+ )
105
+ except ModuleNotFoundError:
106
+ pass # that's ok, we're not instrumenting everything
107
+
108
+ def _uninstrument(self, **kwargs):
109
+ for wrapped_method in WRAPPED_METHODS:
110
+ wrap_package = wrapped_method.get("package")
111
+ wrap_object = wrapped_method.get("object")
112
+ wrap_method = wrapped_method.get("method")
113
+
114
+ unwrap(
115
+ f"{wrap_package}.{wrap_object}" if wrap_object else wrap_package,
116
+ wrap_method,
117
+ )