lmnr 0.6.7__tar.gz → 0.6.8__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.7 → lmnr-0.6.8}/PKG-INFO +1 -1
- {lmnr-0.6.7 → lmnr-0.6.8}/pyproject.toml +1 -1
- {lmnr-0.6.7 → lmnr-0.6.8}/src/lmnr/opentelemetry_lib/decorators/__init__.py +12 -15
- {lmnr-0.6.7 → lmnr-0.6.8}/src/lmnr/opentelemetry_lib/tracing/context_properties.py +6 -0
- {lmnr-0.6.7 → lmnr-0.6.8}/src/lmnr/sdk/decorators.py +12 -0
- {lmnr-0.6.7 → lmnr-0.6.8}/src/lmnr/sdk/laminar.py +145 -28
- {lmnr-0.6.7 → lmnr-0.6.8}/src/lmnr/sdk/utils.py +15 -0
- {lmnr-0.6.7 → lmnr-0.6.8}/src/lmnr/version.py +1 -1
- {lmnr-0.6.7 → lmnr-0.6.8}/LICENSE +0 -0
- {lmnr-0.6.7 → lmnr-0.6.8}/README.md +0 -0
- {lmnr-0.6.7 → lmnr-0.6.8}/src/lmnr/__init__.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.8}/src/lmnr/cli.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.8}/src/lmnr/opentelemetry_lib/.flake8 +0 -0
- {lmnr-0.6.7 → lmnr-0.6.8}/src/lmnr/opentelemetry_lib/__init__.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.8}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/google_genai/__init__.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.8}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/google_genai/config.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.8}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/google_genai/utils.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.8}/src/lmnr/opentelemetry_lib/tracing/__init__.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.8}/src/lmnr/opentelemetry_lib/tracing/_instrument_initializers.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.8}/src/lmnr/opentelemetry_lib/tracing/attributes.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.8}/src/lmnr/opentelemetry_lib/tracing/exporter.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.8}/src/lmnr/opentelemetry_lib/tracing/instruments.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.8}/src/lmnr/opentelemetry_lib/tracing/processor.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.8}/src/lmnr/opentelemetry_lib/tracing/tracer.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.8}/src/lmnr/opentelemetry_lib/utils/__init__.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.8}/src/lmnr/opentelemetry_lib/utils/json_encoder.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.8}/src/lmnr/opentelemetry_lib/utils/package_check.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.8}/src/lmnr/py.typed +0 -0
- {lmnr-0.6.7 → lmnr-0.6.8}/src/lmnr/sdk/__init__.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.8}/src/lmnr/sdk/browser/__init__.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.8}/src/lmnr/sdk/browser/browser_use_otel.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.8}/src/lmnr/sdk/browser/patchright_otel.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.8}/src/lmnr/sdk/browser/playwright_otel.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.8}/src/lmnr/sdk/browser/pw_utils.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.8}/src/lmnr/sdk/browser/rrweb/rrweb.umd.min.cjs +0 -0
- {lmnr-0.6.7 → lmnr-0.6.8}/src/lmnr/sdk/browser/utils.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.8}/src/lmnr/sdk/client/asynchronous/async_client.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.8}/src/lmnr/sdk/client/asynchronous/resources/__init__.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.8}/src/lmnr/sdk/client/asynchronous/resources/agent.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.8}/src/lmnr/sdk/client/asynchronous/resources/base.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.8}/src/lmnr/sdk/client/asynchronous/resources/browser_events.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.8}/src/lmnr/sdk/client/asynchronous/resources/evals.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.8}/src/lmnr/sdk/client/asynchronous/resources/tags.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.8}/src/lmnr/sdk/client/synchronous/resources/__init__.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.8}/src/lmnr/sdk/client/synchronous/resources/agent.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.8}/src/lmnr/sdk/client/synchronous/resources/base.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.8}/src/lmnr/sdk/client/synchronous/resources/browser_events.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.8}/src/lmnr/sdk/client/synchronous/resources/evals.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.8}/src/lmnr/sdk/client/synchronous/resources/tags.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.8}/src/lmnr/sdk/client/synchronous/sync_client.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.8}/src/lmnr/sdk/datasets.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.8}/src/lmnr/sdk/eval_control.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.8}/src/lmnr/sdk/evaluations.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.8}/src/lmnr/sdk/log.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.8}/src/lmnr/sdk/types.py +0 -0
@@ -9,14 +9,15 @@ from opentelemetry import trace
|
|
9
9
|
from opentelemetry import context as context_api
|
10
10
|
from opentelemetry.trace import Span
|
11
11
|
|
12
|
-
from lmnr.opentelemetry_lib.tracing.context_properties import (
|
13
|
-
remove_association_properties,
|
14
|
-
update_association_properties,
|
15
|
-
)
|
16
12
|
from lmnr.sdk.utils import get_input_from_func_args, is_method
|
17
13
|
from lmnr.opentelemetry_lib import MAX_MANUAL_SPAN_PAYLOAD_SIZE
|
18
14
|
from lmnr.opentelemetry_lib.tracing.tracer import get_tracer
|
19
|
-
from lmnr.opentelemetry_lib.tracing.attributes import
|
15
|
+
from lmnr.opentelemetry_lib.tracing.attributes import (
|
16
|
+
ASSOCIATION_PROPERTIES,
|
17
|
+
SPAN_INPUT,
|
18
|
+
SPAN_OUTPUT,
|
19
|
+
SPAN_TYPE,
|
20
|
+
)
|
20
21
|
from lmnr.opentelemetry_lib.tracing import TracerWrapper
|
21
22
|
from lmnr.opentelemetry_lib.utils.json_encoder import JSONEncoder
|
22
23
|
|
@@ -56,11 +57,11 @@ def entity_method(
|
|
56
57
|
|
57
58
|
span_name = name or fn.__name__
|
58
59
|
|
59
|
-
if association_properties is not None:
|
60
|
-
update_association_properties(association_properties)
|
61
|
-
|
62
60
|
with get_tracer() as tracer:
|
63
61
|
span = tracer.start_span(span_name, attributes={SPAN_TYPE: span_type})
|
62
|
+
if association_properties is not None:
|
63
|
+
for key, value in association_properties.items():
|
64
|
+
span.set_attribute(f"{ASSOCIATION_PROPERTIES}.{key}", value)
|
64
65
|
|
65
66
|
ctx = trace.set_span_in_context(span, context_api.get_current())
|
66
67
|
ctx_token = context_api.attach(ctx)
|
@@ -119,8 +120,6 @@ def entity_method(
|
|
119
120
|
|
120
121
|
span.end()
|
121
122
|
context_api.detach(ctx_token)
|
122
|
-
if association_properties is not None:
|
123
|
-
remove_association_properties(association_properties)
|
124
123
|
return res
|
125
124
|
|
126
125
|
return wrap
|
@@ -145,11 +144,11 @@ def aentity_method(
|
|
145
144
|
|
146
145
|
span_name = name or fn.__name__
|
147
146
|
|
148
|
-
if association_properties is not None:
|
149
|
-
update_association_properties(association_properties)
|
150
|
-
|
151
147
|
with get_tracer() as tracer:
|
152
148
|
span = tracer.start_span(span_name, attributes={SPAN_TYPE: span_type})
|
149
|
+
if association_properties is not None:
|
150
|
+
for key, value in association_properties.items():
|
151
|
+
span.set_attribute(f"{ASSOCIATION_PROPERTIES}.{key}", value)
|
153
152
|
|
154
153
|
ctx = trace.set_span_in_context(span, context_api.get_current())
|
155
154
|
ctx_token = context_api.attach(ctx)
|
@@ -200,8 +199,6 @@ def aentity_method(
|
|
200
199
|
pass
|
201
200
|
|
202
201
|
span.end()
|
203
|
-
if association_properties is not None:
|
204
|
-
remove_association_properties(association_properties)
|
205
202
|
context_api.detach(ctx_token)
|
206
203
|
|
207
204
|
return res
|
@@ -10,6 +10,8 @@ from opentelemetry.trace import Span
|
|
10
10
|
from opentelemetry import trace
|
11
11
|
|
12
12
|
|
13
|
+
# TODO: delete this once deprecated Laminar.with_labels is removed. The logic
|
14
|
+
# should be moved into Laminar.set_tracing_level
|
13
15
|
def set_association_properties(properties: dict) -> None:
|
14
16
|
attach(set_value("association_properties", properties))
|
15
17
|
|
@@ -17,10 +19,13 @@ def set_association_properties(properties: dict) -> None:
|
|
17
19
|
_set_association_properties_attributes(span, properties)
|
18
20
|
|
19
21
|
|
22
|
+
# TODO: delete this once deprecated Laminar.with_labels is removed
|
20
23
|
def get_association_properties(context: Context | None = None) -> dict:
|
21
24
|
return get_value("association_properties", context) or {}
|
22
25
|
|
23
26
|
|
27
|
+
# TODO: delete this once deprecated Laminar.with_labels is removed. The logic
|
28
|
+
# should be moved into Laminar.set_tracing_level
|
24
29
|
def update_association_properties(
|
25
30
|
properties: dict,
|
26
31
|
set_on_current_span: bool = True,
|
@@ -37,6 +42,7 @@ def update_association_properties(
|
|
37
42
|
_set_association_properties_attributes(span, properties)
|
38
43
|
|
39
44
|
|
45
|
+
# TODO: this logic should be moved into Laminar.set_tracing_level
|
40
46
|
def remove_association_properties(properties: dict) -> None:
|
41
47
|
props: dict = copy.copy(get_value("association_properties") or {})
|
42
48
|
for k in properties.keys():
|
@@ -9,9 +9,11 @@ from typing import Any, Callable, Literal, TypeVar, cast
|
|
9
9
|
from typing_extensions import ParamSpec
|
10
10
|
|
11
11
|
from lmnr.opentelemetry_lib.tracing.attributes import SESSION_ID
|
12
|
+
from lmnr.sdk.log import get_default_logger
|
12
13
|
|
13
14
|
from .utils import is_async
|
14
15
|
|
16
|
+
logger = get_default_logger(__name__)
|
15
17
|
|
16
18
|
P = ParamSpec("P")
|
17
19
|
R = TypeVar("R")
|
@@ -27,6 +29,7 @@ def observe(
|
|
27
29
|
span_type: Literal["DEFAULT", "LLM", "TOOL"] = "DEFAULT",
|
28
30
|
ignore_inputs: list[str] | None = None,
|
29
31
|
metadata: dict[str, Any] | None = None,
|
32
|
+
tags: list[str] | None = None,
|
30
33
|
) -> Callable[[Callable[P, R]], Callable[P, R]]:
|
31
34
|
"""The main decorator entrypoint for Laminar. This is used to wrap
|
32
35
|
functions and methods to create spans.
|
@@ -52,6 +55,8 @@ def observe(
|
|
52
55
|
this argument. Defaults to None.
|
53
56
|
metadata (dict[str, Any] | None, optional): Metadata to associate with\
|
54
57
|
the trace. Must be JSON serializable. Defaults to None.
|
58
|
+
tags (list[str] | None, optional): Tags to associate with the trace.
|
59
|
+
Defaults to None.
|
55
60
|
Raises:
|
56
61
|
Exception: re-raises the exception if the wrapped function raises an\
|
57
62
|
exception
|
@@ -79,6 +84,13 @@ def observe(
|
|
79
84
|
for k, v in metadata.items()
|
80
85
|
}
|
81
86
|
)
|
87
|
+
if tags is not None:
|
88
|
+
if not isinstance(tags, list) or not all(
|
89
|
+
isinstance(tag, str) for tag in tags
|
90
|
+
):
|
91
|
+
logger.warning("Tags must be a list of strings. Tags will be ignored.")
|
92
|
+
else:
|
93
|
+
association_properties["tags"] = tags
|
82
94
|
result = (
|
83
95
|
aentity_method(
|
84
96
|
name=name,
|
@@ -1,10 +1,13 @@
|
|
1
1
|
from contextlib import contextmanager
|
2
2
|
from contextvars import Context
|
3
|
+
import warnings
|
4
|
+
from typing_extensions import deprecated
|
3
5
|
from lmnr.opentelemetry_lib import TracerManager
|
4
6
|
from lmnr.opentelemetry_lib.tracing.instruments import Instruments
|
5
7
|
from lmnr.opentelemetry_lib.tracing.tracer import get_tracer
|
6
8
|
from lmnr.opentelemetry_lib.tracing.attributes import (
|
7
9
|
ASSOCIATION_PROPERTIES,
|
10
|
+
USER_ID,
|
8
11
|
Attributes,
|
9
12
|
SPAN_TYPE,
|
10
13
|
)
|
@@ -18,7 +21,6 @@ from opentelemetry.util.types import AttributeValue
|
|
18
21
|
|
19
22
|
from typing import Any, Literal
|
20
23
|
|
21
|
-
import copy
|
22
24
|
import datetime
|
23
25
|
import logging
|
24
26
|
import os
|
@@ -37,7 +39,7 @@ from lmnr.opentelemetry_lib.tracing.context_properties import (
|
|
37
39
|
set_association_properties,
|
38
40
|
update_association_properties,
|
39
41
|
)
|
40
|
-
from lmnr.sdk.utils import from_env
|
42
|
+
from lmnr.sdk.utils import from_env, is_otel_attribute_value_type
|
41
43
|
|
42
44
|
from .log import VerboseColorfulFormatter
|
43
45
|
|
@@ -224,6 +226,7 @@ class Laminar:
|
|
224
226
|
context: Context | None = None,
|
225
227
|
labels: list[str] | None = None,
|
226
228
|
parent_span_context: LaminarSpanContext | None = None,
|
229
|
+
tags: list[str] | None = None,
|
227
230
|
):
|
228
231
|
"""Start a new span as the current span. Useful for manual
|
229
232
|
instrumentation. If `span_type` is set to `"LLM"`, you should report
|
@@ -256,8 +259,10 @@ class Laminar:
|
|
256
259
|
`Laminar.get_span_context`, `Laminar.get_span_context_dict` and\
|
257
260
|
`Laminar.get_span_context_str` for more information.
|
258
261
|
Defaults to None.
|
259
|
-
labels (list[str] | None, optional):
|
260
|
-
span. Defaults to None.
|
262
|
+
labels (list[str] | None, optional): [DEPRECATED] Use tags\
|
263
|
+
instead. Labels to set for the span. Defaults to None.
|
264
|
+
tags (list[str] | None, optional): tags to set for the span.
|
265
|
+
Defaults to None.
|
261
266
|
"""
|
262
267
|
|
263
268
|
if not cls.is_initialized():
|
@@ -283,18 +288,32 @@ class Laminar:
|
|
283
288
|
label_props = {}
|
284
289
|
try:
|
285
290
|
if labels:
|
291
|
+
warnings.warn(
|
292
|
+
"`Laminar.start_as_current_span` `labels` is deprecated. Use `tags` instead.",
|
293
|
+
DeprecationWarning,
|
294
|
+
)
|
286
295
|
label_props = {f"{ASSOCIATION_PROPERTIES}.labels": labels}
|
287
296
|
except Exception:
|
288
297
|
cls.__logger.warning(
|
289
298
|
f"`start_as_current_span` Could not set labels: {labels}. "
|
290
299
|
"They will be propagated to the next span."
|
291
300
|
)
|
301
|
+
tag_props = {}
|
302
|
+
if tags:
|
303
|
+
if isinstance(tags, list) and all(isinstance(tag, str) for tag in tags):
|
304
|
+
tag_props = {f"{ASSOCIATION_PROPERTIES}.tags": tags}
|
305
|
+
else:
|
306
|
+
cls.__logger.warning(
|
307
|
+
f"`start_as_current_span` Could not set tags: {tags}. Tags must be a list of strings. "
|
308
|
+
"Tags will be ignored."
|
309
|
+
)
|
292
310
|
with tracer.start_as_current_span(
|
293
311
|
name,
|
294
312
|
context=ctx,
|
295
313
|
attributes={
|
296
314
|
SPAN_TYPE: span_type,
|
297
315
|
**(label_props),
|
316
|
+
**(tag_props),
|
298
317
|
},
|
299
318
|
) as span:
|
300
319
|
if input is not None:
|
@@ -319,6 +338,10 @@ class Laminar:
|
|
319
338
|
|
320
339
|
@classmethod
|
321
340
|
@contextmanager
|
341
|
+
@deprecated(
|
342
|
+
"Use `Laminar.set_span_tags` or the `tags` argument of "
|
343
|
+
"`Laminar.start_as_current_span` or `Laminar.start_span` instead"
|
344
|
+
)
|
322
345
|
def with_labels(cls, labels: list[str], context: Context | None = None):
|
323
346
|
"""Set labels for spans within this `with` context. This is useful for
|
324
347
|
adding labels to the spans created in the auto-instrumentations.
|
@@ -334,6 +357,11 @@ class Laminar:
|
|
334
357
|
openai_client.chat.completions.create()
|
335
358
|
```
|
336
359
|
"""
|
360
|
+
warnings.warn(
|
361
|
+
"`Laminar.with_labels` is deprecated. Use `Laminar.set_span_tags` or the `tags` argument of "
|
362
|
+
"`Laminar.start_as_current_span` or `Laminar.start_span` instead",
|
363
|
+
DeprecationWarning,
|
364
|
+
)
|
337
365
|
if not cls.is_initialized():
|
338
366
|
yield
|
339
367
|
return
|
@@ -365,6 +393,7 @@ class Laminar:
|
|
365
393
|
context: Context | None = None,
|
366
394
|
parent_span_context: LaminarSpanContext | None = None,
|
367
395
|
labels: dict[str, str] | None = None,
|
396
|
+
tags: list[str] | None = None,
|
368
397
|
):
|
369
398
|
"""Start a new span. Useful for manual instrumentation.
|
370
399
|
If `span_type` is set to `"LLM"`, you should report usage and response
|
@@ -416,8 +445,10 @@ class Laminar:
|
|
416
445
|
`Laminar.get_span_context`, `Laminar.get_span_context_dict` and\
|
417
446
|
`Laminar.get_span_context_str` for more information.
|
418
447
|
Defaults to None.
|
419
|
-
|
420
|
-
|
448
|
+
tags (list[str] | None, optional): tags to set for the span.
|
449
|
+
Defaults to None.
|
450
|
+
labels (dict[str, str] | None, optional): [DEPRECATED] Use tags\
|
451
|
+
instead. Labels to set for the span. Defaults to None.
|
421
452
|
"""
|
422
453
|
if not cls.is_initialized():
|
423
454
|
return trace.NonRecordingSpan(
|
@@ -440,6 +471,10 @@ class Laminar:
|
|
440
471
|
label_props = {}
|
441
472
|
try:
|
442
473
|
if labels:
|
474
|
+
warnings.warn(
|
475
|
+
"`Laminar.start_span` `labels` is deprecated. Use `tags` instead.",
|
476
|
+
DeprecationWarning,
|
477
|
+
)
|
443
478
|
label_props = {
|
444
479
|
f"{ASSOCIATION_PROPERTIES}.labels": json_dumps(labels)
|
445
480
|
}
|
@@ -448,12 +483,22 @@ class Laminar:
|
|
448
483
|
f"`start_span` Could not set labels: {labels}. They will be "
|
449
484
|
"propagated to the next span."
|
450
485
|
)
|
486
|
+
tag_props = {}
|
487
|
+
if tags:
|
488
|
+
if isinstance(tags, list) and all(isinstance(tag, str) for tag in tags):
|
489
|
+
tag_props = {f"{ASSOCIATION_PROPERTIES}.tags": tags}
|
490
|
+
else:
|
491
|
+
cls.__logger.warning(
|
492
|
+
f"`start_span` Could not set tags: {tags}. Tags must be a list of strings. "
|
493
|
+
+ "Tags will be ignored."
|
494
|
+
)
|
451
495
|
span = tracer.start_span(
|
452
496
|
name,
|
453
497
|
context=ctx,
|
454
498
|
attributes={
|
455
499
|
SPAN_TYPE: span_type,
|
456
500
|
**(label_props),
|
501
|
+
**(tag_props),
|
457
502
|
},
|
458
503
|
)
|
459
504
|
if input is not None:
|
@@ -562,7 +607,6 @@ class Laminar:
|
|
562
607
|
cls.__logger.warning(
|
563
608
|
f"Attribute {key} is not a valid Laminar attribute."
|
564
609
|
)
|
565
|
-
continue
|
566
610
|
if not isinstance(value, (str, int, float, bool)):
|
567
611
|
span.set_attribute(key.value, json_dumps(value))
|
568
612
|
else:
|
@@ -649,11 +693,30 @@ class Laminar:
|
|
649
693
|
TracerManager.shutdown()
|
650
694
|
|
651
695
|
@classmethod
|
696
|
+
def set_span_tags(cls, tags: list[str]):
|
697
|
+
"""Set the tags for the current span.
|
698
|
+
|
699
|
+
Args:
|
700
|
+
tags (list[str]): Tags to set for the span.
|
701
|
+
"""
|
702
|
+
span = trace.get_current_span()
|
703
|
+
if span == trace.INVALID_SPAN:
|
704
|
+
cls.__logger.warning("No active span to set tags on")
|
705
|
+
return
|
706
|
+
if not isinstance(tags, list) or not all(isinstance(tag, str) for tag in tags):
|
707
|
+
cls.__logger.warning(
|
708
|
+
"Tags must be a list of strings. Tags will be ignored."
|
709
|
+
)
|
710
|
+
return
|
711
|
+
span.set_attribute(f"{ASSOCIATION_PROPERTIES}.tags", tags)
|
712
|
+
|
713
|
+
@classmethod
|
714
|
+
@deprecated("Use `Laminar.set_trace_session_id` instead")
|
652
715
|
def set_session(
|
653
716
|
cls,
|
654
717
|
session_id: str | None = None,
|
655
718
|
):
|
656
|
-
"""Set the session
|
719
|
+
"""Set the session id for the current span and the context
|
657
720
|
(i.e. any children spans created from the current span in the current
|
658
721
|
thread).
|
659
722
|
|
@@ -663,12 +726,53 @@ class Laminar:
|
|
663
726
|
sessions/conversations.
|
664
727
|
Defaults to None.
|
665
728
|
"""
|
729
|
+
warnings.warn(
|
730
|
+
"`Laminar.set_session` is deprecated. Use `Laminar.set_trace_session_id` instead",
|
731
|
+
DeprecationWarning,
|
732
|
+
)
|
666
733
|
association_properties = {}
|
667
734
|
if session_id is not None:
|
668
735
|
association_properties[SESSION_ID] = session_id
|
669
|
-
update_association_properties(association_properties)
|
736
|
+
# update_association_properties(association_properties)
|
737
|
+
span = trace.get_current_span()
|
738
|
+
if span == trace.INVALID_SPAN:
|
739
|
+
cls.__logger.warning("No active span to set session id on")
|
740
|
+
return
|
741
|
+
if session_id is not None:
|
742
|
+
span.set_attribute(f"{ASSOCIATION_PROPERTIES}.{SESSION_ID}", session_id)
|
743
|
+
|
744
|
+
@classmethod
|
745
|
+
def set_trace_session_id(cls, session_id: str | None = None):
|
746
|
+
"""Set the session id for the current trace.
|
747
|
+
Overrides any existing session id.
|
748
|
+
|
749
|
+
Args:
|
750
|
+
session_id (str | None, optional): Custom session id. Defaults to None.
|
751
|
+
"""
|
752
|
+
span = trace.get_current_span()
|
753
|
+
if span == trace.INVALID_SPAN:
|
754
|
+
cls.__logger.warning("No active span to set session id on")
|
755
|
+
return
|
756
|
+
if session_id is not None:
|
757
|
+
span.set_attribute(f"{ASSOCIATION_PROPERTIES}.{SESSION_ID}", session_id)
|
670
758
|
|
671
759
|
@classmethod
|
760
|
+
def set_trace_user_id(cls, user_id: str | None = None):
|
761
|
+
"""Set the user id for the current trace.
|
762
|
+
Overrides any existing user id.
|
763
|
+
|
764
|
+
Args:
|
765
|
+
user_id (str | None, optional): Custom user id. Defaults to None.
|
766
|
+
"""
|
767
|
+
span = trace.get_current_span()
|
768
|
+
if span == trace.INVALID_SPAN:
|
769
|
+
cls.__logger.warning("No active span to set user id on")
|
770
|
+
return
|
771
|
+
if user_id is not None:
|
772
|
+
span.set_attribute(f"{ASSOCIATION_PROPERTIES}.{USER_ID}", user_id)
|
773
|
+
|
774
|
+
@classmethod
|
775
|
+
@deprecated("Use `Laminar.set_trace_metadata` instead")
|
672
776
|
def set_metadata(cls, metadata: dict[str, str]):
|
673
777
|
"""Set the metadata for the current trace.
|
674
778
|
|
@@ -676,25 +780,37 @@ class Laminar:
|
|
676
780
|
metadata (dict[str, str]): Metadata to set for the trace. Will be\
|
677
781
|
sent as attributes, so must be json serializable.
|
678
782
|
"""
|
783
|
+
warnings.warn(
|
784
|
+
"`Laminar.set_metadata` is deprecated. Use `Laminar.set_trace_metadata` instead",
|
785
|
+
DeprecationWarning,
|
786
|
+
)
|
679
787
|
props = {f"metadata.{k}": json_dumps(v) for k, v in metadata.items()}
|
680
|
-
update_association_properties(props)
|
788
|
+
# update_association_properties(props)
|
789
|
+
span = trace.get_current_span()
|
790
|
+
if span == trace.INVALID_SPAN:
|
791
|
+
cls.__logger.warning("No active span to set metadata on")
|
792
|
+
return
|
793
|
+
for key, value in props.items():
|
794
|
+
span.set_attribute(key, value)
|
681
795
|
|
682
796
|
@classmethod
|
683
|
-
def
|
684
|
-
"""
|
685
|
-
props: dict = copy.copy(context_api.get_value("association_properties"))
|
686
|
-
metadata_keys = [k for k in props.keys() if k.startswith("metadata.")]
|
687
|
-
for k in metadata_keys:
|
688
|
-
props.pop(k)
|
689
|
-
set_association_properties(props)
|
797
|
+
def set_trace_metadata(cls, metadata: dict[str, AttributeValue]):
|
798
|
+
"""Set the metadata for the current trace.
|
690
799
|
|
691
|
-
|
692
|
-
|
693
|
-
"""
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
800
|
+
Args:
|
801
|
+
metadata (dict[str, AttributeValue]): Metadata to set for the trace.
|
802
|
+
"""
|
803
|
+
span = trace.get_current_span()
|
804
|
+
if span == trace.INVALID_SPAN:
|
805
|
+
cls.__logger.warning("No active span to set metadata on")
|
806
|
+
return
|
807
|
+
for key, value in metadata.items():
|
808
|
+
if is_otel_attribute_value_type(value):
|
809
|
+
span.set_attribute(f"{ASSOCIATION_PROPERTIES}.metadata.{key}", value)
|
810
|
+
else:
|
811
|
+
span.set_attribute(
|
812
|
+
f"{ASSOCIATION_PROPERTIES}.metadata.{key}", json_dumps(value)
|
813
|
+
)
|
698
814
|
|
699
815
|
@classmethod
|
700
816
|
def get_base_http_url(cls):
|
@@ -735,7 +851,8 @@ class Laminar:
|
|
735
851
|
Args:
|
736
852
|
trace_type (TraceType): Type of the trace
|
737
853
|
"""
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
854
|
+
span = trace.get_current_span()
|
855
|
+
if span == trace.INVALID_SPAN:
|
856
|
+
cls.__logger.warning("No active span to set trace type on")
|
857
|
+
return
|
858
|
+
span.set_attribute(f"{ASSOCIATION_PROPERTIES}.{TRACE_TYPE}", trace_type.value)
|
@@ -113,3 +113,18 @@ def from_env(key: str) -> str | None:
|
|
113
113
|
dotenv_path = dotenv.find_dotenv(usecwd=True)
|
114
114
|
# use DotEnv directly so we can set verbose to False
|
115
115
|
return dotenv.main.DotEnv(dotenv_path, verbose=False, encoding="utf-8").get(key)
|
116
|
+
|
117
|
+
|
118
|
+
def is_otel_attribute_value_type(value: typing.Any) -> bool:
|
119
|
+
def is_primitive_type(value: typing.Any) -> bool:
|
120
|
+
return isinstance(value, (int, float, str, bool))
|
121
|
+
|
122
|
+
if is_primitive_type(value):
|
123
|
+
return True
|
124
|
+
elif isinstance(value, typing.Sequence):
|
125
|
+
if len(value) > 0:
|
126
|
+
return is_primitive_type(value[0]) and all(
|
127
|
+
isinstance(v, type(value[0])) for v in value
|
128
|
+
)
|
129
|
+
return True
|
130
|
+
return False
|
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
|
File without changes
|
File without changes
|