lmnr 0.4.62__tar.gz → 0.4.64__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.4.62 → lmnr-0.4.64}/PKG-INFO +1 -1
- {lmnr-0.4.62 → lmnr-0.4.64}/pyproject.toml +1 -1
- {lmnr-0.4.62 → lmnr-0.4.64}/src/lmnr/__init__.py +1 -0
- {lmnr-0.4.62 → lmnr-0.4.64}/src/lmnr/openllmetry_sdk/__init__.py +5 -0
- {lmnr-0.4.62 → lmnr-0.4.64}/src/lmnr/openllmetry_sdk/tracing/tracing.py +16 -15
- {lmnr-0.4.62 → lmnr-0.4.64}/src/lmnr/sdk/laminar.py +151 -39
- {lmnr-0.4.62 → lmnr-0.4.64}/src/lmnr/sdk/types.py +86 -0
- {lmnr-0.4.62 → lmnr-0.4.64}/src/lmnr/version.py +1 -1
- {lmnr-0.4.62 → lmnr-0.4.64}/LICENSE +0 -0
- {lmnr-0.4.62 → lmnr-0.4.64}/README.md +0 -0
- {lmnr-0.4.62 → lmnr-0.4.64}/src/lmnr/cli.py +0 -0
- {lmnr-0.4.62 → lmnr-0.4.64}/src/lmnr/openllmetry_sdk/.flake8 +0 -0
- {lmnr-0.4.62 → lmnr-0.4.64}/src/lmnr/openllmetry_sdk/config/__init__.py +0 -0
- {lmnr-0.4.62 → lmnr-0.4.64}/src/lmnr/openllmetry_sdk/decorators/__init__.py +0 -0
- {lmnr-0.4.62 → lmnr-0.4.64}/src/lmnr/openllmetry_sdk/decorators/base.py +0 -0
- {lmnr-0.4.62 → lmnr-0.4.64}/src/lmnr/openllmetry_sdk/instruments.py +0 -0
- {lmnr-0.4.62 → lmnr-0.4.64}/src/lmnr/openllmetry_sdk/tracing/__init__.py +0 -0
- {lmnr-0.4.62 → lmnr-0.4.64}/src/lmnr/openllmetry_sdk/tracing/attributes.py +0 -0
- {lmnr-0.4.62 → lmnr-0.4.64}/src/lmnr/openllmetry_sdk/tracing/content_allow_list.py +0 -0
- {lmnr-0.4.62 → lmnr-0.4.64}/src/lmnr/openllmetry_sdk/tracing/context_manager.py +0 -0
- {lmnr-0.4.62 → lmnr-0.4.64}/src/lmnr/openllmetry_sdk/utils/__init__.py +0 -0
- {lmnr-0.4.62 → lmnr-0.4.64}/src/lmnr/openllmetry_sdk/utils/in_memory_span_exporter.py +0 -0
- {lmnr-0.4.62 → lmnr-0.4.64}/src/lmnr/openllmetry_sdk/utils/json_encoder.py +0 -0
- {lmnr-0.4.62 → lmnr-0.4.64}/src/lmnr/openllmetry_sdk/utils/package_check.py +0 -0
- {lmnr-0.4.62 → lmnr-0.4.64}/src/lmnr/py.typed +0 -0
- {lmnr-0.4.62 → lmnr-0.4.64}/src/lmnr/sdk/__init__.py +0 -0
- {lmnr-0.4.62 → lmnr-0.4.64}/src/lmnr/sdk/browser/__init__.py +0 -0
- {lmnr-0.4.62 → lmnr-0.4.64}/src/lmnr/sdk/browser/playwright_patch.py +0 -0
- {lmnr-0.4.62 → lmnr-0.4.64}/src/lmnr/sdk/browser/rrweb/rrweb.min.js +0 -0
- {lmnr-0.4.62 → lmnr-0.4.64}/src/lmnr/sdk/datasets.py +0 -0
- {lmnr-0.4.62 → lmnr-0.4.64}/src/lmnr/sdk/decorators.py +0 -0
- {lmnr-0.4.62 → lmnr-0.4.64}/src/lmnr/sdk/eval_control.py +0 -0
- {lmnr-0.4.62 → lmnr-0.4.64}/src/lmnr/sdk/evaluations.py +0 -0
- {lmnr-0.4.62 → lmnr-0.4.64}/src/lmnr/sdk/log.py +0 -0
- {lmnr-0.4.62 → lmnr-0.4.64}/src/lmnr/sdk/utils.py +0 -0
@@ -10,6 +10,7 @@ from .sdk.types import (
|
|
10
10
|
TracingLevel,
|
11
11
|
)
|
12
12
|
from .sdk.decorators import observe
|
13
|
+
from .sdk.types import LaminarSpanContext
|
13
14
|
from .openllmetry_sdk import Instruments
|
14
15
|
from .openllmetry_sdk.tracing.attributes import Attributes
|
15
16
|
from opentelemetry.trace import use_span
|
@@ -38,7 +38,7 @@ from opentelemetry.sdk.trace.export import (
|
|
38
38
|
SimpleSpanProcessor,
|
39
39
|
BatchSpanProcessor,
|
40
40
|
)
|
41
|
-
from opentelemetry.trace import
|
41
|
+
from opentelemetry.sdk.trace import SpanLimits
|
42
42
|
|
43
43
|
from typing import Dict, Optional, Set
|
44
44
|
|
@@ -69,6 +69,8 @@ EXCLUDED_URLS = """
|
|
69
69
|
githubusercontent.com,
|
70
70
|
openaipublic.blob.core.windows.net"""
|
71
71
|
|
72
|
+
MAX_EVENTS_OR_ATTRIBUTES_PER_SPAN = 5000
|
73
|
+
|
72
74
|
|
73
75
|
class TracerWrapper(object):
|
74
76
|
resource_attributes: dict = {}
|
@@ -291,22 +293,21 @@ def init_spans_exporter(api_endpoint: str, headers: Dict[str, str]) -> SpanExpor
|
|
291
293
|
)
|
292
294
|
|
293
295
|
|
296
|
+
# TODO: check if it's safer to use the default tracer provider obtained from
|
297
|
+
# get_tracer_provider()
|
294
298
|
def init_tracer_provider(resource: Resource) -> TracerProvider:
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
return
|
306
|
-
else:
|
307
|
-
provider = default_provider
|
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
|
+
)
|
308
309
|
|
309
|
-
return
|
310
|
+
return tracer_provider
|
310
311
|
|
311
312
|
|
312
313
|
def init_instrumentations(
|
@@ -13,7 +13,6 @@ from lmnr.openllmetry_sdk.config import MAX_MANUAL_SPAN_PAYLOAD_SIZE
|
|
13
13
|
from lmnr.openllmetry_sdk.decorators.base import json_dumps
|
14
14
|
from opentelemetry import context as context_api, trace
|
15
15
|
from opentelemetry.context import attach, detach
|
16
|
-
from lmnr.version import SDK_VERSION, get_latest_pypi_version, is_latest_version
|
17
16
|
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import (
|
18
17
|
OTLPSpanExporter,
|
19
18
|
Compression,
|
@@ -36,6 +35,7 @@ import requests
|
|
36
35
|
import re
|
37
36
|
import urllib.parse
|
38
37
|
import uuid
|
38
|
+
import warnings
|
39
39
|
|
40
40
|
from lmnr.openllmetry_sdk.tracing.attributes import (
|
41
41
|
SESSION_ID,
|
@@ -55,6 +55,7 @@ from .types import (
|
|
55
55
|
InitEvaluationResponse,
|
56
56
|
EvaluationResultDatapoint,
|
57
57
|
GetDatapointsResponse,
|
58
|
+
LaminarSpanContext,
|
58
59
|
PipelineRunError,
|
59
60
|
PipelineRunResponse,
|
60
61
|
NodeInput,
|
@@ -347,8 +348,10 @@ class Laminar:
|
|
347
348
|
Literal["DEFAULT"], Literal["LLM"], Literal["TOOL"]
|
348
349
|
] = "DEFAULT",
|
349
350
|
context: Optional[Context] = None,
|
350
|
-
trace_id: Optional[uuid.UUID] = None,
|
351
351
|
labels: Optional[dict[str, str]] = None,
|
352
|
+
parent_span_context: Optional[LaminarSpanContext] = None,
|
353
|
+
# deprecated, use parent_span_context instead
|
354
|
+
trace_id: Optional[uuid.UUID] = None,
|
352
355
|
):
|
353
356
|
"""Start a new span as the current span. Useful for manual
|
354
357
|
instrumentation. If `span_type` is set to `"LLM"`, you should report
|
@@ -371,11 +374,21 @@ class Laminar:
|
|
371
374
|
and response attributes manually. Defaults to "DEFAULT".
|
372
375
|
context (Optional[Context], optional): raw OpenTelemetry context\
|
373
376
|
to attach the span to. Defaults to None.
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
+
parent_span_context (Optional[LaminarSpanContext], optional): parent\
|
378
|
+
span context to use for the span. Useful for continuing traces\
|
379
|
+
across services. If parent_span_context is a\
|
380
|
+
raw OpenTelemetry span context, or if it is a dictionary or string\
|
381
|
+
obtained from `Laminar.get_laminar_span_context_dict()` or\
|
382
|
+
`Laminar.get_laminar_span_context_str()` respectively, it will be\
|
383
|
+
converted to a `LaminarSpanContext` if possible. See also\
|
384
|
+
`Laminar.get_span_context`, `Laminar.get_span_context_dict` and\
|
385
|
+
`Laminar.get_span_context_str` for more information.
|
386
|
+
Defaults to None.
|
377
387
|
labels (Optional[dict[str, str]], optional): labels to set for the\
|
378
388
|
span. Defaults to None.
|
389
|
+
trace_id (Optional[uuid.UUID], optional): [Deprecated] override\
|
390
|
+
the trace id for the span. If not provided, use the current\
|
391
|
+
trace id. Defaults to None.
|
379
392
|
"""
|
380
393
|
|
381
394
|
if not cls.is_initialized():
|
@@ -385,21 +398,29 @@ class Laminar:
|
|
385
398
|
with get_tracer() as tracer:
|
386
399
|
ctx = context or context_api.get_current()
|
387
400
|
if trace_id is not None:
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
401
|
+
warnings.warn(
|
402
|
+
"trace_id provided to `Laminar.start_as_current_span`"
|
403
|
+
" is deprecated, use parent_span_context instead",
|
404
|
+
DeprecationWarning,
|
405
|
+
stacklevel=2,
|
406
|
+
)
|
407
|
+
if parent_span_context is not None:
|
408
|
+
span_context = LaminarSpanContext.try_to_otel_span_context(
|
409
|
+
parent_span_context, cls.__logger
|
410
|
+
)
|
411
|
+
ctx = trace.set_span_in_context(
|
412
|
+
trace.NonRecordingSpan(span_context), ctx
|
413
|
+
)
|
414
|
+
elif trace_id is not None and isinstance(trace_id, uuid.UUID):
|
415
|
+
span_context = trace.SpanContext(
|
416
|
+
trace_id=int(trace_id),
|
417
|
+
span_id=random.getrandbits(64),
|
418
|
+
is_remote=False,
|
419
|
+
trace_flags=trace.TraceFlags(trace.TraceFlags.SAMPLED),
|
420
|
+
)
|
421
|
+
ctx = trace.set_span_in_context(
|
422
|
+
trace.NonRecordingSpan(span_context), ctx
|
423
|
+
)
|
403
424
|
ctx_token = attach(ctx)
|
404
425
|
label_props = {}
|
405
426
|
try:
|
@@ -487,8 +508,10 @@ class Laminar:
|
|
487
508
|
Literal["DEFAULT"], Literal["LLM"], Literal["TOOL"]
|
488
509
|
] = "DEFAULT",
|
489
510
|
context: Optional[Context] = None,
|
490
|
-
|
511
|
+
parent_span_context: Optional[LaminarSpanContext] = None,
|
491
512
|
labels: Optional[dict[str, str]] = None,
|
513
|
+
# deprecated, use parent_span_context instead
|
514
|
+
trace_id: Optional[uuid.UUID] = None,
|
492
515
|
):
|
493
516
|
"""Start a new span. Useful for manual instrumentation.
|
494
517
|
If `span_type` is set to `"LLM"`, you should report usage and response
|
@@ -530,30 +553,48 @@ class Laminar:
|
|
530
553
|
and response attributes manually. Defaults to "DEFAULT".
|
531
554
|
context (Optional[Context], optional): raw OpenTelemetry context\
|
532
555
|
to attach the span to. Defaults to None.
|
533
|
-
|
534
|
-
|
535
|
-
|
556
|
+
parent_span_context (Optional[LaminarSpanContext], optional): parent\
|
557
|
+
span context to use for the span. Useful for continuing traces\
|
558
|
+
across services. If parent_span_context is a\
|
559
|
+
raw OpenTelemetry span context, or if it is a dictionary or string\
|
560
|
+
obtained from `Laminar.get_laminar_span_context_dict()` or\
|
561
|
+
`Laminar.get_laminar_span_context_str()` respectively, it will be\
|
562
|
+
converted to a `LaminarSpanContext` if possible. See also\
|
563
|
+
`Laminar.get_span_context`, `Laminar.get_span_context_dict` and\
|
564
|
+
`Laminar.get_span_context_str` for more information.
|
565
|
+
Defaults to None.
|
536
566
|
labels (Optional[dict[str, str]], optional): labels to set for the\
|
537
567
|
span. Defaults to None.
|
568
|
+
trace_id (Optional[uuid.UUID], optional): Deprecated, use\
|
569
|
+
`parent_span_context` instead. If provided, it will be used to\
|
570
|
+
set the trace id for the span.
|
538
571
|
"""
|
539
572
|
with get_tracer() as tracer:
|
540
573
|
ctx = context or context_api.get_current()
|
541
574
|
if trace_id is not None:
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
575
|
+
warnings.warn(
|
576
|
+
"trace_id provided to `Laminar.start_span`"
|
577
|
+
" is deprecated, use parent_span_context instead",
|
578
|
+
DeprecationWarning,
|
579
|
+
stacklevel=2,
|
580
|
+
)
|
581
|
+
if parent_span_context is not None:
|
582
|
+
span_context = LaminarSpanContext.try_to_otel_span_context(
|
583
|
+
parent_span_context, cls.__logger
|
584
|
+
)
|
585
|
+
ctx = trace.set_span_in_context(
|
586
|
+
trace.NonRecordingSpan(span_context), ctx
|
587
|
+
)
|
588
|
+
elif trace_id is not None and isinstance(trace_id, uuid.UUID):
|
589
|
+
span_context = trace.SpanContext(
|
590
|
+
trace_id=int(trace_id),
|
591
|
+
span_id=random.getrandbits(64),
|
592
|
+
is_remote=False,
|
593
|
+
trace_flags=trace.TraceFlags(trace.TraceFlags.SAMPLED),
|
594
|
+
)
|
595
|
+
ctx = trace.set_span_in_context(
|
596
|
+
trace.NonRecordingSpan(span_context), ctx
|
597
|
+
)
|
557
598
|
label_props = {}
|
558
599
|
try:
|
559
600
|
if labels:
|
@@ -688,6 +729,77 @@ class Laminar:
|
|
688
729
|
else:
|
689
730
|
span.set_attribute(key.value, value)
|
690
731
|
|
732
|
+
@classmethod
|
733
|
+
def get_laminar_span_context(
|
734
|
+
cls, span: Optional[trace.Span] = None
|
735
|
+
) -> Optional[LaminarSpanContext]:
|
736
|
+
"""Get the laminar span context for a given span.
|
737
|
+
If no span is provided, the current active span will be used.
|
738
|
+
"""
|
739
|
+
span = span or trace.get_current_span()
|
740
|
+
if span == trace.INVALID_SPAN:
|
741
|
+
return None
|
742
|
+
return LaminarSpanContext(
|
743
|
+
trace_id=uuid.UUID(int=span.get_span_context().trace_id),
|
744
|
+
span_id=uuid.UUID(int=span.get_span_context().span_id),
|
745
|
+
is_remote=span.get_span_context().is_remote,
|
746
|
+
)
|
747
|
+
|
748
|
+
@classmethod
|
749
|
+
def get_laminar_span_context_dict(
|
750
|
+
cls, span: Optional[trace.Span] = None
|
751
|
+
) -> Optional[dict]:
|
752
|
+
"""Get the laminar span context for a given span as a dictionary.
|
753
|
+
If no span is provided, the current active span will be used.
|
754
|
+
|
755
|
+
This is useful for continuing a trace across services.
|
756
|
+
|
757
|
+
Example:
|
758
|
+
```python
|
759
|
+
# service A:
|
760
|
+
with Laminar.start_as_current_span("service_a"):
|
761
|
+
span_context = Laminar.get_laminar_span_context_dict()
|
762
|
+
# send span_context to service B
|
763
|
+
call_service_b(request, headers={"laminar-span-context": span_context})
|
764
|
+
|
765
|
+
# service B:
|
766
|
+
def call_service_b(request, headers):
|
767
|
+
span_context = LaminarSpanContext.from_dict(headers["laminar-span-context"])
|
768
|
+
with Laminar.start_as_current_span("service_b", parent_span_context=span_context):
|
769
|
+
# rest of the function
|
770
|
+
pass
|
771
|
+
```
|
772
|
+
|
773
|
+
This will result in a trace like:
|
774
|
+
```
|
775
|
+
service_a
|
776
|
+
service_b
|
777
|
+
```
|
778
|
+
"""
|
779
|
+
span_context = cls.get_laminar_span_context(span)
|
780
|
+
if span_context is None:
|
781
|
+
return None
|
782
|
+
return span_context.to_dict()
|
783
|
+
|
784
|
+
@classmethod
|
785
|
+
def get_laminar_span_context_str(
|
786
|
+
cls, span: Optional[trace.Span] = None
|
787
|
+
) -> Optional[str]:
|
788
|
+
span_context = cls.get_laminar_span_context(span)
|
789
|
+
if span_context is None:
|
790
|
+
return None
|
791
|
+
return json.dumps(span_context.to_dict())
|
792
|
+
|
793
|
+
@classmethod
|
794
|
+
def deserialize_laminar_span_context(
|
795
|
+
cls, span_context: Union[dict, str]
|
796
|
+
) -> LaminarSpanContext:
|
797
|
+
return LaminarSpanContext.deserialize(span_context)
|
798
|
+
|
799
|
+
@classmethod
|
800
|
+
def shutdown(cls):
|
801
|
+
Traceloop.flush()
|
802
|
+
|
691
803
|
@classmethod
|
692
804
|
def set_session(
|
693
805
|
cls,
|
@@ -1,6 +1,9 @@
|
|
1
|
+
import logging
|
1
2
|
import aiohttp
|
2
3
|
import datetime
|
3
4
|
from enum import Enum
|
5
|
+
import json
|
6
|
+
from opentelemetry.trace import SpanContext, TraceFlags
|
4
7
|
import pydantic
|
5
8
|
from typing import Any, Awaitable, Callable, Optional, Union
|
6
9
|
import uuid
|
@@ -210,3 +213,86 @@ class TracingLevel(Enum):
|
|
210
213
|
OFF = 0
|
211
214
|
META_ONLY = 1
|
212
215
|
ALL = 2
|
216
|
+
|
217
|
+
|
218
|
+
class LaminarSpanContext(pydantic.BaseModel):
|
219
|
+
"""
|
220
|
+
A span context that can be used to continue a trace across services. This
|
221
|
+
is a slightly modified version of the OpenTelemetry span context. For
|
222
|
+
usage examples, see `Laminar.get_laminar_span_context_dict`,
|
223
|
+
`Laminar.get_laminar_span_context_str`, `Laminar.get_span_context`, and
|
224
|
+
`Laminar.deserialize_laminar_span_context`.
|
225
|
+
|
226
|
+
The difference between this and the OpenTelemetry span context is that
|
227
|
+
the `trace_id` and `span_id` are stored as UUIDs instead of integers for
|
228
|
+
easier debugging, and the separate trace flags are not currently stored.
|
229
|
+
"""
|
230
|
+
|
231
|
+
trace_id: uuid.UUID
|
232
|
+
span_id: uuid.UUID
|
233
|
+
is_remote: bool = pydantic.Field(default=False)
|
234
|
+
|
235
|
+
# uuid is not serializable by default, so we need to convert it to a string
|
236
|
+
def to_dict(self):
|
237
|
+
return {
|
238
|
+
"traceId": str(self.trace_id),
|
239
|
+
"spanId": str(self.span_id),
|
240
|
+
"isRemote": self.is_remote,
|
241
|
+
}
|
242
|
+
|
243
|
+
@classmethod
|
244
|
+
def from_dict(cls, data: dict[str, Any]) -> "LaminarSpanContext":
|
245
|
+
return cls(
|
246
|
+
trace_id=uuid.UUID(data["traceId"]),
|
247
|
+
span_id=uuid.UUID(data["spanId"]),
|
248
|
+
is_remote=data["isRemote"],
|
249
|
+
)
|
250
|
+
|
251
|
+
@classmethod
|
252
|
+
def try_to_otel_span_context(
|
253
|
+
cls,
|
254
|
+
span_context: Union["LaminarSpanContext", dict[str, Any], str, SpanContext],
|
255
|
+
logger: Optional[logging.Logger] = None,
|
256
|
+
) -> SpanContext:
|
257
|
+
if logger is None:
|
258
|
+
logger = logging.getLogger(__name__)
|
259
|
+
|
260
|
+
if isinstance(span_context, LaminarSpanContext):
|
261
|
+
return SpanContext(
|
262
|
+
trace_id=span_context.trace_id.int,
|
263
|
+
span_id=span_context.span_id.int,
|
264
|
+
is_remote=span_context.is_remote,
|
265
|
+
trace_flags=TraceFlags(TraceFlags.SAMPLED),
|
266
|
+
)
|
267
|
+
elif isinstance(span_context, SpanContext) or (
|
268
|
+
isinstance(getattr(span_context, "trace_id", None), int)
|
269
|
+
and isinstance(getattr(span_context, "span_id", None), int)
|
270
|
+
):
|
271
|
+
logger.warning(
|
272
|
+
"span_context provided"
|
273
|
+
" is likely a raw OpenTelemetry span context. Will try to use it. "
|
274
|
+
"Please use `LaminarSpanContext` instead."
|
275
|
+
)
|
276
|
+
return span_context
|
277
|
+
elif isinstance(span_context, dict) or isinstance(span_context, str):
|
278
|
+
try:
|
279
|
+
laminar_span_context = cls.deserialize(span_context)
|
280
|
+
return SpanContext(
|
281
|
+
trace_id=laminar_span_context.trace_id.int,
|
282
|
+
span_id=laminar_span_context.span_id.int,
|
283
|
+
is_remote=laminar_span_context.is_remote,
|
284
|
+
trace_flags=TraceFlags(TraceFlags.SAMPLED),
|
285
|
+
)
|
286
|
+
except Exception:
|
287
|
+
raise ValueError("Invalid span_context provided")
|
288
|
+
else:
|
289
|
+
raise ValueError("Invalid span_context provided")
|
290
|
+
|
291
|
+
@classmethod
|
292
|
+
def deserialize(cls, data: Union[dict[str, Any], str]) -> "LaminarSpanContext":
|
293
|
+
if isinstance(data, dict):
|
294
|
+
return cls.from_dict(data)
|
295
|
+
elif isinstance(data, str):
|
296
|
+
return cls.from_dict(json.loads(data))
|
297
|
+
else:
|
298
|
+
raise ValueError("Invalid span_context provided")
|
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
|