lmnr 0.6.9__tar.gz → 0.6.10__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 (58) hide show
  1. {lmnr-0.6.9 → lmnr-0.6.10}/PKG-INFO +1 -1
  2. {lmnr-0.6.9 → lmnr-0.6.10}/pyproject.toml +1 -1
  3. {lmnr-0.6.9 → lmnr-0.6.10}/src/lmnr/cli.py +16 -3
  4. {lmnr-0.6.9 → lmnr-0.6.10}/src/lmnr/opentelemetry_lib/__init__.py +2 -0
  5. {lmnr-0.6.9 → lmnr-0.6.10}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/langgraph/__init__.py +4 -2
  6. lmnr-0.6.10/src/lmnr/opentelemetry_lib/tracing/__init__.py +162 -0
  7. {lmnr-0.6.9 → lmnr-0.6.10}/src/lmnr/sdk/client/asynchronous/resources/evals.py +4 -0
  8. {lmnr-0.6.9 → lmnr-0.6.10}/src/lmnr/sdk/client/synchronous/resources/evals.py +4 -0
  9. {lmnr-0.6.9 → lmnr-0.6.10}/src/lmnr/sdk/evaluations.py +10 -15
  10. {lmnr-0.6.9 → lmnr-0.6.10}/src/lmnr/sdk/laminar.py +7 -0
  11. {lmnr-0.6.9 → lmnr-0.6.10}/src/lmnr/version.py +1 -1
  12. lmnr-0.6.9/src/lmnr/opentelemetry_lib/tracing/__init__.py +0 -157
  13. {lmnr-0.6.9 → lmnr-0.6.10}/LICENSE +0 -0
  14. {lmnr-0.6.9 → lmnr-0.6.10}/README.md +0 -0
  15. {lmnr-0.6.9 → lmnr-0.6.10}/src/lmnr/__init__.py +0 -0
  16. {lmnr-0.6.9 → lmnr-0.6.10}/src/lmnr/opentelemetry_lib/.flake8 +0 -0
  17. {lmnr-0.6.9 → lmnr-0.6.10}/src/lmnr/opentelemetry_lib/decorators/__init__.py +0 -0
  18. {lmnr-0.6.9 → lmnr-0.6.10}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/google_genai/__init__.py +0 -0
  19. {lmnr-0.6.9 → lmnr-0.6.10}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/google_genai/config.py +0 -0
  20. {lmnr-0.6.9 → lmnr-0.6.10}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/google_genai/utils.py +0 -0
  21. {lmnr-0.6.9 → lmnr-0.6.10}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/langgraph/utils.py +0 -0
  22. {lmnr-0.6.9 → lmnr-0.6.10}/src/lmnr/opentelemetry_lib/tracing/_instrument_initializers.py +0 -0
  23. {lmnr-0.6.9 → lmnr-0.6.10}/src/lmnr/opentelemetry_lib/tracing/attributes.py +0 -0
  24. {lmnr-0.6.9 → lmnr-0.6.10}/src/lmnr/opentelemetry_lib/tracing/context_properties.py +0 -0
  25. {lmnr-0.6.9 → lmnr-0.6.10}/src/lmnr/opentelemetry_lib/tracing/exporter.py +0 -0
  26. {lmnr-0.6.9 → lmnr-0.6.10}/src/lmnr/opentelemetry_lib/tracing/instruments.py +0 -0
  27. {lmnr-0.6.9 → lmnr-0.6.10}/src/lmnr/opentelemetry_lib/tracing/processor.py +0 -0
  28. {lmnr-0.6.9 → lmnr-0.6.10}/src/lmnr/opentelemetry_lib/tracing/tracer.py +0 -0
  29. {lmnr-0.6.9 → lmnr-0.6.10}/src/lmnr/opentelemetry_lib/utils/__init__.py +0 -0
  30. {lmnr-0.6.9 → lmnr-0.6.10}/src/lmnr/opentelemetry_lib/utils/json_encoder.py +0 -0
  31. {lmnr-0.6.9 → lmnr-0.6.10}/src/lmnr/opentelemetry_lib/utils/package_check.py +0 -0
  32. {lmnr-0.6.9 → lmnr-0.6.10}/src/lmnr/py.typed +0 -0
  33. {lmnr-0.6.9 → lmnr-0.6.10}/src/lmnr/sdk/__init__.py +0 -0
  34. {lmnr-0.6.9 → lmnr-0.6.10}/src/lmnr/sdk/browser/__init__.py +0 -0
  35. {lmnr-0.6.9 → lmnr-0.6.10}/src/lmnr/sdk/browser/browser_use_otel.py +0 -0
  36. {lmnr-0.6.9 → lmnr-0.6.10}/src/lmnr/sdk/browser/patchright_otel.py +0 -0
  37. {lmnr-0.6.9 → lmnr-0.6.10}/src/lmnr/sdk/browser/playwright_otel.py +0 -0
  38. {lmnr-0.6.9 → lmnr-0.6.10}/src/lmnr/sdk/browser/pw_utils.py +0 -0
  39. {lmnr-0.6.9 → lmnr-0.6.10}/src/lmnr/sdk/browser/rrweb/rrweb.umd.min.cjs +0 -0
  40. {lmnr-0.6.9 → lmnr-0.6.10}/src/lmnr/sdk/browser/utils.py +0 -0
  41. {lmnr-0.6.9 → lmnr-0.6.10}/src/lmnr/sdk/client/asynchronous/async_client.py +0 -0
  42. {lmnr-0.6.9 → lmnr-0.6.10}/src/lmnr/sdk/client/asynchronous/resources/__init__.py +0 -0
  43. {lmnr-0.6.9 → lmnr-0.6.10}/src/lmnr/sdk/client/asynchronous/resources/agent.py +0 -0
  44. {lmnr-0.6.9 → lmnr-0.6.10}/src/lmnr/sdk/client/asynchronous/resources/base.py +0 -0
  45. {lmnr-0.6.9 → lmnr-0.6.10}/src/lmnr/sdk/client/asynchronous/resources/browser_events.py +0 -0
  46. {lmnr-0.6.9 → lmnr-0.6.10}/src/lmnr/sdk/client/asynchronous/resources/tags.py +0 -0
  47. {lmnr-0.6.9 → lmnr-0.6.10}/src/lmnr/sdk/client/synchronous/resources/__init__.py +0 -0
  48. {lmnr-0.6.9 → lmnr-0.6.10}/src/lmnr/sdk/client/synchronous/resources/agent.py +0 -0
  49. {lmnr-0.6.9 → lmnr-0.6.10}/src/lmnr/sdk/client/synchronous/resources/base.py +0 -0
  50. {lmnr-0.6.9 → lmnr-0.6.10}/src/lmnr/sdk/client/synchronous/resources/browser_events.py +0 -0
  51. {lmnr-0.6.9 → lmnr-0.6.10}/src/lmnr/sdk/client/synchronous/resources/tags.py +0 -0
  52. {lmnr-0.6.9 → lmnr-0.6.10}/src/lmnr/sdk/client/synchronous/sync_client.py +0 -0
  53. {lmnr-0.6.9 → lmnr-0.6.10}/src/lmnr/sdk/datasets.py +0 -0
  54. {lmnr-0.6.9 → lmnr-0.6.10}/src/lmnr/sdk/decorators.py +0 -0
  55. {lmnr-0.6.9 → lmnr-0.6.10}/src/lmnr/sdk/eval_control.py +0 -0
  56. {lmnr-0.6.9 → lmnr-0.6.10}/src/lmnr/sdk/log.py +0 -0
  57. {lmnr-0.6.9 → lmnr-0.6.10}/src/lmnr/sdk/types.py +0 -0
  58. {lmnr-0.6.9 → lmnr-0.6.10}/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.9
3
+ Version: 0.6.10
4
4
  Summary: Python SDK for Laminar
5
5
  License: Apache-2.0
6
6
  Author: lmnr.ai
@@ -6,7 +6,7 @@
6
6
 
7
7
  [project]
8
8
  name = "lmnr"
9
- version = "0.6.9"
9
+ version = "0.6.10"
10
10
  description = "Python SDK for Laminar"
11
11
  authors = [
12
12
  { name = "lmnr.ai", email = "founders@lmnr.ai" }
@@ -100,9 +100,14 @@ async def run_evaluation(args):
100
100
  sys.modules[name] = mod
101
101
 
102
102
  spec.loader.exec_module(mod)
103
- evaluations: list[Evaluation] | None = EVALUATION_INSTANCES.get()
104
- if evaluations is None:
105
- LOG.warning("Evaluation instance not found")
103
+ evaluations = []
104
+ try:
105
+ evaluations: list[Evaluation] | None = EVALUATION_INSTANCES.get()
106
+ if evaluations is None:
107
+ raise LookupError()
108
+ # may be raised by `get()` or manually by us above
109
+ except LookupError:
110
+ log_evaluation_instance_not_found()
106
111
  if args.continue_on_error:
107
112
  continue
108
113
  return
@@ -130,6 +135,14 @@ async def run_evaluation(args):
130
135
  PREPARE_ONLY.reset(prep_token)
131
136
 
132
137
 
138
+ def log_evaluation_instance_not_found():
139
+ LOG.warning(
140
+ "Evaluation instance not found. "
141
+ "`evaluate` must be called at the top level of the file, "
142
+ "not inside a function when running evaluations from the CLI."
143
+ )
144
+
145
+
133
146
  def cli():
134
147
  parser = ArgumentParser(
135
148
  prog="lmnr",
@@ -54,6 +54,8 @@ class TracerManager:
54
54
 
55
55
  @staticmethod
56
56
  def flush() -> bool:
57
+ if not hasattr(TracerManager, "_TracerManager__tracer_wrapper"):
58
+ return False
57
59
  return TracerManager.__tracer_wrapper.flush()
58
60
 
59
61
  @staticmethod
@@ -11,7 +11,7 @@ from .utils import (
11
11
  from langchain_core.runnables.graph import Graph
12
12
  from opentelemetry.trace import Tracer
13
13
  from wrapt import wrap_function_wrapper
14
- from opentelemetry.trace import get_tracer, get_current_span
14
+ from opentelemetry.trace import get_tracer
15
15
 
16
16
  from lmnr.opentelemetry_lib.tracing.context_properties import (
17
17
  update_association_properties,
@@ -81,7 +81,9 @@ async def async_wrap_pregel_stream(
81
81
  "langgraph.nodes": json.dumps(nodes),
82
82
  },
83
83
  )
84
- return await wrapped(*args, **kwargs)
84
+
85
+ async for item in wrapped(*args, **kwargs):
86
+ yield item
85
87
 
86
88
 
87
89
  class LanggraphInstrumentor(BaseInstrumentor):
@@ -0,0 +1,162 @@
1
+ import atexit
2
+ import logging
3
+ import threading
4
+
5
+ from lmnr.opentelemetry_lib.tracing.processor import LaminarSpanProcessor
6
+ from lmnr.sdk.client.asynchronous.async_client import AsyncLaminarClient
7
+ from lmnr.sdk.client.synchronous.sync_client import LaminarClient
8
+ from lmnr.sdk.log import VerboseColorfulFormatter
9
+ from lmnr.opentelemetry_lib.tracing.instruments import (
10
+ Instruments,
11
+ init_instrumentations,
12
+ )
13
+
14
+ from opentelemetry import trace
15
+ from opentelemetry.instrumentation.threading import ThreadingInstrumentor
16
+ from opentelemetry.sdk.resources import Resource
17
+ from opentelemetry.sdk.trace import TracerProvider, SpanProcessor
18
+ from opentelemetry.sdk.trace.export import SpanExporter
19
+
20
+ TRACER_NAME = "lmnr.tracer"
21
+
22
+ MAX_EVENTS_OR_ATTRIBUTES_PER_SPAN = 5000
23
+
24
+
25
+ class TracerWrapper(object):
26
+ resource_attributes: dict = {}
27
+ enable_content_tracing: bool = True
28
+ _lock = threading.Lock()
29
+ _tracer_provider: TracerProvider | None = None
30
+ _logger: logging.Logger
31
+ _client: LaminarClient
32
+ _async_client: AsyncLaminarClient
33
+ _resource: Resource
34
+ _span_processor: SpanProcessor
35
+
36
+ def __new__(
37
+ cls,
38
+ disable_batch=False,
39
+ exporter: SpanExporter | None = None,
40
+ instruments: set[Instruments] | None = None,
41
+ block_instruments: set[Instruments] | None = None,
42
+ base_url: str = "https://api.lmnr.ai",
43
+ port: int = 8443,
44
+ http_port: int = 443,
45
+ project_api_key: str | None = None,
46
+ max_export_batch_size: int | None = None,
47
+ force_http: bool = False,
48
+ timeout_seconds: int = 10,
49
+ set_global_tracer_provider: bool = True,
50
+ otel_logger_level: int = logging.ERROR,
51
+ ) -> "TracerWrapper":
52
+ # Silence some opentelemetry warnings
53
+ logging.getLogger("opentelemetry.trace").setLevel(otel_logger_level)
54
+
55
+ base_http_url = f"{base_url}:{http_port}"
56
+ with cls._lock:
57
+ if not hasattr(cls, "instance"):
58
+ cls._initialize_logger(cls)
59
+ obj = super(TracerWrapper, cls).__new__(cls)
60
+
61
+ obj._client = LaminarClient(
62
+ base_url=base_http_url,
63
+ project_api_key=project_api_key,
64
+ )
65
+ obj._async_client = AsyncLaminarClient(
66
+ base_url=base_http_url,
67
+ project_api_key=project_api_key,
68
+ )
69
+
70
+ obj._resource = Resource(attributes=TracerWrapper.resource_attributes)
71
+
72
+ obj._span_processor = LaminarSpanProcessor(
73
+ base_url=base_url,
74
+ api_key=project_api_key,
75
+ port=http_port if force_http else port,
76
+ exporter=exporter,
77
+ max_export_batch_size=max_export_batch_size,
78
+ timeout_seconds=timeout_seconds,
79
+ force_http=force_http,
80
+ disable_batch=disable_batch,
81
+ )
82
+
83
+ lmnr_provider = TracerProvider(resource=obj._resource)
84
+ global_provider = trace.get_tracer_provider()
85
+ if set_global_tracer_provider and isinstance(
86
+ global_provider, trace.ProxyTracerProvider
87
+ ):
88
+ trace.set_tracer_provider(lmnr_provider)
89
+
90
+ obj._tracer_provider = lmnr_provider
91
+
92
+ obj._tracer_provider.add_span_processor(obj._span_processor)
93
+
94
+ # This is not a real instrumentation and does not generate telemetry
95
+ # data, but it is required to ensure that OpenTelemetry context
96
+ # propagation is enabled.
97
+ # See the README at:
98
+ # https://pypi.org/project/opentelemetry-instrumentation-threading/
99
+ ThreadingInstrumentor().instrument()
100
+
101
+ init_instrumentations(
102
+ tracer_provider=obj._tracer_provider,
103
+ instruments=instruments,
104
+ block_instruments=block_instruments,
105
+ client=obj._client,
106
+ async_client=obj._async_client,
107
+ )
108
+
109
+ cls.instance = obj
110
+
111
+ # Force flushes for debug environments (e.g. local development)
112
+ atexit.register(obj.exit_handler)
113
+
114
+ return cls.instance
115
+
116
+ def exit_handler(self):
117
+ if isinstance(self._span_processor, LaminarSpanProcessor):
118
+ self._span_processor.clear()
119
+ self.flush()
120
+
121
+ def _initialize_logger(self):
122
+ self._logger = logging.getLogger(__name__)
123
+ console_log_handler = logging.StreamHandler()
124
+ console_log_handler.setFormatter(VerboseColorfulFormatter())
125
+ self._logger.addHandler(console_log_handler)
126
+
127
+ @staticmethod
128
+ def set_static_params(
129
+ resource_attributes: dict,
130
+ enable_content_tracing: bool,
131
+ ) -> None:
132
+ TracerWrapper.resource_attributes = resource_attributes
133
+ TracerWrapper.enable_content_tracing = enable_content_tracing
134
+
135
+ @classmethod
136
+ def verify_initialized(cls) -> bool:
137
+ with cls._lock:
138
+ return hasattr(cls, "instance") and hasattr(cls.instance, "_span_processor")
139
+
140
+ @classmethod
141
+ def clear(cls):
142
+ if not cls.verify_initialized():
143
+ return
144
+ # Any state cleanup. Now used in between tests
145
+ if isinstance(cls.instance._span_processor, LaminarSpanProcessor):
146
+ cls.instance._span_processor.clear()
147
+
148
+ def shutdown(self):
149
+ if self._tracer_provider is None:
150
+ return
151
+ self._tracer_provider.shutdown()
152
+
153
+ def flush(self):
154
+ if not hasattr(self, "_span_processor"):
155
+ self._logger.warning("TracerWrapper not fully initialized, cannot flush")
156
+ return False
157
+ return self._span_processor.force_flush()
158
+
159
+ def get_tracer(self):
160
+ if self._tracer_provider is None:
161
+ return trace.get_tracer_provider().get_tracer(TRACER_NAME)
162
+ return self._tracer_provider.get_tracer(TRACER_NAME)
@@ -33,6 +33,10 @@ class AsyncEvals(BaseAsyncResource):
33
33
  },
34
34
  headers=self._headers(),
35
35
  )
36
+ if response.status_code != 200:
37
+ if response.status_code == 401:
38
+ raise ValueError("Unauthorized. Please check your project API key.")
39
+ raise ValueError(f"Error initializing evaluation: {response.text}")
36
40
  resp_json = response.json()
37
41
  return InitEvaluationResponse.model_validate(resp_json)
38
42
 
@@ -35,6 +35,10 @@ class Evals(BaseResource):
35
35
  },
36
36
  headers=self._headers(),
37
37
  )
38
+ if response.status_code != 200:
39
+ if response.status_code == 401:
40
+ raise ValueError("Unauthorized. Please check your project API key.")
41
+ raise ValueError(f"Error initializing evaluation: {response.text}")
38
42
  resp_json = response.json()
39
43
  return InitEvaluationResponse.model_validate(resp_json)
40
44
 
@@ -199,11 +199,11 @@ class Evaluation:
199
199
  self.base_http_url = f"{base_url}:{http_port or 443}"
200
200
 
201
201
  api_key = project_api_key or from_env("LMNR_PROJECT_API_KEY")
202
- if not api_key:
202
+ if not api_key and not L.is_initialized():
203
203
  raise ValueError(
204
- "Please initialize the Laminar object with"
205
- " your project API key or set the LMNR_PROJECT_API_KEY"
206
- " environment variable in your environment or .env file"
204
+ "Please pass the project API key to `evaluate`"
205
+ " or set the LMNR_PROJECT_API_KEY environment variable"
206
+ " in your environment or .env file"
207
207
  )
208
208
  self.project_api_key = api_key
209
209
 
@@ -212,17 +212,12 @@ class Evaluation:
212
212
  base_url=L.get_base_http_url(),
213
213
  project_api_key=L.get_project_api_key(),
214
214
  )
215
- if project_api_key and project_api_key != L.get_project_api_key():
216
- self._logger.warning(
217
- "Project API key is different from the one used to initialize"
218
- " Laminar. Ignoring the project API key passed to the evaluation."
219
- )
220
- return
215
+ else:
216
+ self.client = AsyncLaminarClient(
217
+ base_url=self.base_http_url,
218
+ project_api_key=self.project_api_key,
219
+ )
221
220
 
222
- self.client = AsyncLaminarClient(
223
- base_url=self.base_http_url,
224
- project_api_key=self.project_api_key,
225
- )
226
221
  L.initialize(
227
222
  project_api_key=project_api_key,
228
223
  base_url=base_url,
@@ -261,7 +256,7 @@ class Evaluation:
261
256
  except Exception as e:
262
257
  self.reporter.stopWithError(e)
263
258
  await self._shutdown()
264
- return {}
259
+ raise
265
260
 
266
261
  average_scores = get_average_scores(result_datapoints)
267
262
  self.reporter.stop(average_scores, evaluation.projectId, evaluation.id)
@@ -114,6 +114,12 @@ class Laminar:
114
114
  Raises:
115
115
  ValueError: If project API key is not set
116
116
  """
117
+ if cls.is_initialized():
118
+ cls.__logger.info(
119
+ "Laminar is already initialized. Skipping initialization."
120
+ )
121
+ return
122
+
117
123
  cls.__project_api_key = project_api_key or from_env("LMNR_PROJECT_API_KEY")
118
124
  if not cls.__project_api_key:
119
125
  raise ValueError(
@@ -691,6 +697,7 @@ class Laminar:
691
697
  def shutdown(cls):
692
698
  if cls.is_initialized():
693
699
  TracerManager.shutdown()
700
+ cls.__initialized = False
694
701
 
695
702
  @classmethod
696
703
  def set_span_tags(cls, tags: list[str]):
@@ -3,7 +3,7 @@ import httpx
3
3
  from packaging import version
4
4
 
5
5
 
6
- __version__ = "0.6.9"
6
+ __version__ = "0.6.10"
7
7
  PYTHON_VERSION = f"{sys.version_info.major}.{sys.version_info.minor}"
8
8
 
9
9
 
@@ -1,157 +0,0 @@
1
- import atexit
2
- import logging
3
-
4
- from lmnr.opentelemetry_lib.tracing.processor import LaminarSpanProcessor
5
- from lmnr.sdk.client.asynchronous.async_client import AsyncLaminarClient
6
- from lmnr.sdk.client.synchronous.sync_client import LaminarClient
7
- from lmnr.sdk.log import VerboseColorfulFormatter
8
- from lmnr.opentelemetry_lib.tracing.instruments import (
9
- Instruments,
10
- init_instrumentations,
11
- )
12
-
13
- from opentelemetry import trace
14
- from opentelemetry.instrumentation.threading import ThreadingInstrumentor
15
- from opentelemetry.sdk.resources import Resource
16
- from opentelemetry.sdk.trace import TracerProvider, SpanProcessor
17
- from opentelemetry.sdk.trace.export import SpanExporter
18
-
19
- module_logger = logging.getLogger(__name__)
20
- console_log_handler = logging.StreamHandler()
21
- console_log_handler.setFormatter(VerboseColorfulFormatter())
22
- module_logger.addHandler(console_log_handler)
23
-
24
-
25
- TRACER_NAME = "lmnr.tracer"
26
-
27
- MAX_EVENTS_OR_ATTRIBUTES_PER_SPAN = 5000
28
-
29
-
30
- class TracerWrapper(object):
31
- resource_attributes: dict = {}
32
- enable_content_tracing: bool = True
33
- __tracer_provider: TracerProvider | None = None
34
- __logger: logging.Logger
35
- __client: LaminarClient
36
- __async_client: AsyncLaminarClient
37
- __resource: Resource
38
- __span_processor: SpanProcessor
39
-
40
- def __new__(
41
- cls,
42
- disable_batch=False,
43
- exporter: SpanExporter | None = None,
44
- instruments: set[Instruments] | None = None,
45
- block_instruments: set[Instruments] | None = None,
46
- base_url: str = "https://api.lmnr.ai",
47
- port: int = 8443,
48
- http_port: int = 443,
49
- project_api_key: str | None = None,
50
- max_export_batch_size: int | None = None,
51
- force_http: bool = False,
52
- timeout_seconds: int = 10,
53
- set_global_tracer_provider: bool = True,
54
- otel_logger_level: int = logging.ERROR,
55
- ) -> "TracerWrapper":
56
- # Silence some opentelemetry warnings
57
- logging.getLogger("opentelemetry.trace").setLevel(otel_logger_level)
58
-
59
- base_http_url = f"{base_url}:{http_port}"
60
- cls._initialize_logger(cls)
61
- if not hasattr(cls, "instance"):
62
- obj = cls.instance = super(TracerWrapper, cls).__new__(cls)
63
-
64
- obj.__client = LaminarClient(
65
- base_url=base_http_url,
66
- project_api_key=project_api_key,
67
- )
68
- obj.__async_client = AsyncLaminarClient(
69
- base_url=base_http_url,
70
- project_api_key=project_api_key,
71
- )
72
-
73
- obj.__resource = Resource(attributes=TracerWrapper.resource_attributes)
74
-
75
- obj.__span_processor = LaminarSpanProcessor(
76
- base_url=base_url,
77
- api_key=project_api_key,
78
- port=http_port if force_http else port,
79
- exporter=exporter,
80
- max_export_batch_size=max_export_batch_size,
81
- timeout_seconds=timeout_seconds,
82
- force_http=force_http,
83
- disable_batch=disable_batch,
84
- )
85
-
86
- lmnr_provider = TracerProvider(resource=obj.__resource)
87
- global_provider = trace.get_tracer_provider()
88
- if set_global_tracer_provider and isinstance(
89
- global_provider, trace.ProxyTracerProvider
90
- ):
91
- trace.set_tracer_provider(lmnr_provider)
92
-
93
- obj.__tracer_provider = lmnr_provider
94
-
95
- obj.__tracer_provider.add_span_processor(obj.__span_processor)
96
-
97
- # This is not a real instrumentation and does not generate telemetry
98
- # data, but it is required to ensure that OpenTelemetry context
99
- # propagation is enabled.
100
- # See the README at:
101
- # https://pypi.org/project/opentelemetry-instrumentation-threading/
102
- ThreadingInstrumentor().instrument()
103
-
104
- init_instrumentations(
105
- tracer_provider=obj.__tracer_provider,
106
- instruments=instruments,
107
- block_instruments=block_instruments,
108
- client=obj.__client,
109
- async_client=obj.__async_client,
110
- )
111
-
112
- # Force flushes for debug environments (e.g. local development)
113
- atexit.register(obj.exit_handler)
114
-
115
- return cls.instance
116
-
117
- def exit_handler(self):
118
- if isinstance(self.__span_processor, LaminarSpanProcessor):
119
- self.__span_processor.clear()
120
- self.flush()
121
-
122
- def _initialize_logger(self):
123
- self.__logger = logging.getLogger(__name__)
124
- console_log_handler = logging.StreamHandler()
125
- console_log_handler.setFormatter(VerboseColorfulFormatter())
126
- self.__logger.addHandler(console_log_handler)
127
-
128
- @staticmethod
129
- def set_static_params(
130
- resource_attributes: dict,
131
- enable_content_tracing: bool,
132
- ) -> None:
133
- TracerWrapper.resource_attributes = resource_attributes
134
- TracerWrapper.enable_content_tracing = enable_content_tracing
135
-
136
- @classmethod
137
- def verify_initialized(cls) -> bool:
138
- return hasattr(cls, "instance")
139
-
140
- @classmethod
141
- def clear(cls):
142
- # Any state cleanup. Now used in between tests
143
- if isinstance(cls.instance.__span_processor, LaminarSpanProcessor):
144
- cls.instance.__span_processor.clear()
145
-
146
- def shutdown(self):
147
- if self.__tracer_provider is None:
148
- return
149
- self.__tracer_provider.shutdown()
150
-
151
- def flush(self):
152
- return self.__span_processor.force_flush()
153
-
154
- def get_tracer(self):
155
- if self.__tracer_provider is None:
156
- return trace.get_tracer_provider().get_tracer(TRACER_NAME)
157
- return self.__tracer_provider.get_tracer(TRACER_NAME)
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