latitude-telemetry 0.1.0b1__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 (27) hide show
  1. latitude_telemetry-0.1.0b1/.gitignore +141 -0
  2. latitude_telemetry-0.1.0b1/.python-version +1 -0
  3. latitude_telemetry-0.1.0b1/PKG-INFO +71 -0
  4. latitude_telemetry-0.1.0b1/README.md +33 -0
  5. latitude_telemetry-0.1.0b1/pyproject.toml +90 -0
  6. latitude_telemetry-0.1.0b1/scripts/format.py +8 -0
  7. latitude_telemetry-0.1.0b1/scripts/lint.py +9 -0
  8. latitude_telemetry-0.1.0b1/scripts/test.py +7 -0
  9. latitude_telemetry-0.1.0b1/src/latitude_telemetry/__init__.py +1 -0
  10. latitude_telemetry-0.1.0b1/src/latitude_telemetry/env/__init__.py +1 -0
  11. latitude_telemetry-0.1.0b1/src/latitude_telemetry/env/env.py +18 -0
  12. latitude_telemetry-0.1.0b1/src/latitude_telemetry/exporter/__init__.py +2 -0
  13. latitude_telemetry-0.1.0b1/src/latitude_telemetry/exporter/exporter.py +172 -0
  14. latitude_telemetry-0.1.0b1/src/latitude_telemetry/exporter/payloads.py +62 -0
  15. latitude_telemetry-0.1.0b1/src/latitude_telemetry/py.typed +0 -0
  16. latitude_telemetry-0.1.0b1/src/latitude_telemetry/telemetry/__init__.py +2 -0
  17. latitude_telemetry-0.1.0b1/src/latitude_telemetry/telemetry/telemetry.py +238 -0
  18. latitude_telemetry-0.1.0b1/src/latitude_telemetry/telemetry/types.py +57 -0
  19. latitude_telemetry-0.1.0b1/src/latitude_telemetry/util/__init__.py +1 -0
  20. latitude_telemetry-0.1.0b1/src/latitude_telemetry/util/utils.py +103 -0
  21. latitude_telemetry-0.1.0b1/tests/__init__.py +0 -0
  22. latitude_telemetry-0.1.0b1/tests/telemetry/__init__.py +0 -0
  23. latitude_telemetry-0.1.0b1/tests/telemetry/instrument_test.py +7 -0
  24. latitude_telemetry-0.1.0b1/tests/utils/__init__.py +2 -0
  25. latitude_telemetry-0.1.0b1/tests/utils/fixtures.py +0 -0
  26. latitude_telemetry-0.1.0b1/tests/utils/utils.py +71 -0
  27. latitude_telemetry-0.1.0b1/uv.lock +1313 -0
@@ -0,0 +1,141 @@
1
+ # Custom
2
+ .vscode/
3
+ .superinvoke_cache/
4
+ .idea/
5
+ *.tmlanguage.cache
6
+ *.tmPreferences.cache
7
+ *.stTheme.cache
8
+ *.sublime-workspace
9
+ .DS_Store
10
+ *.env
11
+
12
+ # Byte-compiled / optimized / DLL files
13
+ __pycache__/
14
+ *.py[cod]
15
+ *$py.class
16
+
17
+ # C extensions
18
+ *.so
19
+
20
+ # Distribution / packaging
21
+ .Python
22
+ build/
23
+ develop-eggs/
24
+ dist/
25
+ downloads/
26
+ eggs/
27
+ .eggs/
28
+ lib/
29
+ lib64/
30
+ parts/
31
+ sdist/
32
+ var/
33
+ wheels/
34
+ share/python-wheels/
35
+ *.egg-info/
36
+ .installed.cfg
37
+ *.egg
38
+ MANIFEST
39
+
40
+ # PyInstaller
41
+ *.manifest
42
+ *.spec
43
+
44
+ # Installer logs
45
+ pip-log.txt
46
+ pip-delete-this-directory.txt
47
+
48
+ # Unit test / coverage reports
49
+ htmlcov/
50
+ .tox/
51
+ .nox/
52
+ .coverage
53
+ .coverage.*
54
+ .cache
55
+ nosetests.xml
56
+ coverage.xml
57
+ *.cover
58
+ *.py,cover
59
+ .hypothesis/
60
+ .pytest_cache/
61
+ cover/
62
+
63
+ # Translations
64
+ *.mo
65
+ *.pot
66
+
67
+ # Django stuff:
68
+ *.log
69
+ local_settings.py
70
+ db.sqlite3
71
+ db.sqlite3-journal
72
+
73
+ # Flask stuff:
74
+ instance/
75
+ .webassets-cache
76
+
77
+ # Scrapy stuff:
78
+ .scrapy
79
+
80
+ # Sphinx documentation
81
+ docs/_build/
82
+
83
+ # PyBuilder
84
+ .pybuilder/
85
+ target/
86
+
87
+ # Jupyter Notebook
88
+ .ipynb_checkpoints
89
+
90
+ # IPython
91
+ profile_default/
92
+ ipython_config.py
93
+
94
+ # pyenv
95
+ -
96
+
97
+ # pdm
98
+ .pdm.toml
99
+
100
+ # PEP 582
101
+ __pypackages__/
102
+
103
+ # Celery stuff
104
+ celerybeat-schedule
105
+ celerybeat.pid
106
+
107
+ # SageMath parsed files
108
+ *.sage.py
109
+
110
+ # Environments
111
+ .env
112
+ .venv
113
+ venv/
114
+ venv.bak/
115
+
116
+ # Spyder project settings
117
+ .spyderproject
118
+ .spyproject
119
+
120
+ # Rope project settings
121
+ .ropeproject
122
+
123
+ # mkdocs documentation
124
+ /site
125
+
126
+ # mypy
127
+ .mypy_cache/
128
+ .dmypy.json
129
+ dmypy.json
130
+
131
+ # Pyre type checker
132
+ .pyre/
133
+
134
+ # pytype static type analyzer
135
+ .pytype/
136
+
137
+ # Cython debug symbols
138
+ cython_debug/
139
+
140
+ # Ruff
141
+ .ruff_cache/
@@ -0,0 +1 @@
1
+ 3.9.21
@@ -0,0 +1,71 @@
1
+ Metadata-Version: 2.4
2
+ Name: latitude-telemetry
3
+ Version: 0.1.0b1
4
+ Summary: Latitude Telemetry for Python
5
+ Project-URL: repository, https://github.com/latitude-dev/latitude-llm/tree/main/packages/telemetry/python
6
+ Project-URL: homepage, https://github.com/latitude-dev/latitude-llm/tree/main/packages/telemetry/python#readme
7
+ Project-URL: documentation, https://github.com/latitude-dev/latitude-llm/tree/main/packages/telemetry/python#readme
8
+ Author-email: Latitude Data SL <hello@latitude.so>
9
+ Maintainer-email: Latitude Data SL <hello@latitude.so>
10
+ License-Expression: LGPL-3.0
11
+ Requires-Python: >=3.9
12
+ Requires-Dist: httpx>=0.27.2
13
+ Requires-Dist: openinference-instrumentation-litellm>=0.1.5
14
+ Requires-Dist: opentelemetry-api>=1.29.0
15
+ Requires-Dist: opentelemetry-instrumentation-alephalpha>=0.36.0
16
+ Requires-Dist: opentelemetry-instrumentation-anthropic>=0.36.0
17
+ Requires-Dist: opentelemetry-instrumentation-bedrock>=0.36.0
18
+ Requires-Dist: opentelemetry-instrumentation-cohere>=0.36.0
19
+ Requires-Dist: opentelemetry-instrumentation-google-generativeai>=0.36.0
20
+ Requires-Dist: opentelemetry-instrumentation-groq>=0.36.0
21
+ Requires-Dist: opentelemetry-instrumentation-haystack>=0.36.0
22
+ Requires-Dist: opentelemetry-instrumentation-langchain>=0.36.0
23
+ Requires-Dist: opentelemetry-instrumentation-llamaindex>=0.36.0
24
+ Requires-Dist: opentelemetry-instrumentation-mistralai>=0.36.0
25
+ Requires-Dist: opentelemetry-instrumentation-ollama>=0.36.0
26
+ Requires-Dist: opentelemetry-instrumentation-openai>=0.36.0
27
+ Requires-Dist: opentelemetry-instrumentation-replicate>=0.36.0
28
+ Requires-Dist: opentelemetry-instrumentation-sagemaker>=0.36.0
29
+ Requires-Dist: opentelemetry-instrumentation-threading>=0.50b0
30
+ Requires-Dist: opentelemetry-instrumentation-together>=0.36.0
31
+ Requires-Dist: opentelemetry-instrumentation-transformers>=0.36.0
32
+ Requires-Dist: opentelemetry-instrumentation-vertexai>=0.36.0
33
+ Requires-Dist: opentelemetry-instrumentation-watsonx>=0.36.0
34
+ Requires-Dist: opentelemetry-sdk>=1.29.0
35
+ Requires-Dist: pydantic>=2.10.3
36
+ Requires-Dist: typing-extensions>=4.12.2
37
+ Description-Content-Type: text/markdown
38
+
39
+ # Latitude Telemetry for Python
40
+
41
+ ```sh
42
+ pip install latitude-telemetry
43
+ ```
44
+
45
+ Requires Python `3.9` or higher.
46
+
47
+ Go to the [documentation](TODO) to learn more.
48
+
49
+ ## Usage
50
+
51
+ ```python
52
+ TODO
53
+ ```
54
+
55
+ Find more [examples](TODO).
56
+
57
+ ## Development
58
+
59
+ Requires uv `0.5.10` or higher.
60
+
61
+ - Install dependencies: `uv venv && uv sync --all-extras --all-groups`
62
+ - Add [dev] dependencies: `uv add [--dev] <package>`
63
+ - Run linter: `uv run scripts/lint.py`
64
+ - Run formatter: `uv run scripts/format.py`
65
+ - Run tests: `uv run scripts/test.py`
66
+ - Build package: `uv build`
67
+ - Publish package: `uv publish`
68
+
69
+ ## License
70
+
71
+ The Telemetry is licensed under the [LGPL-3.0 License](https://opensource.org/licenses/LGPL-3.0) - read the [LICENSE](/LICENSE) file for details.
@@ -0,0 +1,33 @@
1
+ # Latitude Telemetry for Python
2
+
3
+ ```sh
4
+ pip install latitude-telemetry
5
+ ```
6
+
7
+ Requires Python `3.9` or higher.
8
+
9
+ Go to the [documentation](TODO) to learn more.
10
+
11
+ ## Usage
12
+
13
+ ```python
14
+ TODO
15
+ ```
16
+
17
+ Find more [examples](TODO).
18
+
19
+ ## Development
20
+
21
+ Requires uv `0.5.10` or higher.
22
+
23
+ - Install dependencies: `uv venv && uv sync --all-extras --all-groups`
24
+ - Add [dev] dependencies: `uv add [--dev] <package>`
25
+ - Run linter: `uv run scripts/lint.py`
26
+ - Run formatter: `uv run scripts/format.py`
27
+ - Run tests: `uv run scripts/test.py`
28
+ - Build package: `uv build`
29
+ - Publish package: `uv publish`
30
+
31
+ ## License
32
+
33
+ The Telemetry is licensed under the [LGPL-3.0 License](https://opensource.org/licenses/LGPL-3.0) - read the [LICENSE](/LICENSE) file for details.
@@ -0,0 +1,90 @@
1
+ [project]
2
+ name = "latitude-telemetry"
3
+ version = "0.1.0-beta.1"
4
+ description = "Latitude Telemetry for Python"
5
+ authors = [{ name = "Latitude Data SL", email = "hello@latitude.so" }]
6
+ maintainers = [{ name = "Latitude Data SL", email = "hello@latitude.so" }]
7
+ readme = "README.md"
8
+ license = "LGPL-3.0"
9
+ urls.repository = "https://github.com/latitude-dev/latitude-llm/tree/main/packages/telemetry/python"
10
+ urls.homepage = "https://github.com/latitude-dev/latitude-llm/tree/main/packages/telemetry/python#readme"
11
+ urls.documentation = "https://github.com/latitude-dev/latitude-llm/tree/main/packages/telemetry/python#readme"
12
+ requires-python = ">=3.9"
13
+ dependencies = [
14
+ "opentelemetry-api>=1.29.0",
15
+ "opentelemetry-sdk>=1.29.0",
16
+ "opentelemetry-instrumentation-alephalpha>=0.36.0",
17
+ "opentelemetry-instrumentation-anthropic>=0.36.0",
18
+ "opentelemetry-instrumentation-bedrock>=0.36.0",
19
+ "opentelemetry-instrumentation-cohere>=0.36.0",
20
+ "opentelemetry-instrumentation-google-generativeai>=0.36.0",
21
+ "opentelemetry-instrumentation-groq>=0.36.0",
22
+ "opentelemetry-instrumentation-haystack>=0.36.0",
23
+ "opentelemetry-instrumentation-langchain>=0.36.0",
24
+ "openinference-instrumentation-litellm>=0.1.5",
25
+ "opentelemetry-instrumentation-llamaindex>=0.36.0",
26
+ "opentelemetry-instrumentation-mistralai>=0.36.0",
27
+ "opentelemetry-instrumentation-ollama>=0.36.0",
28
+ "opentelemetry-instrumentation-openai>=0.36.0",
29
+ "opentelemetry-instrumentation-replicate>=0.36.0",
30
+ "opentelemetry-instrumentation-sagemaker>=0.36.0",
31
+ "opentelemetry-instrumentation-together>=0.36.0",
32
+ "opentelemetry-instrumentation-threading>=0.50b0",
33
+ "opentelemetry-instrumentation-transformers>=0.36.0",
34
+ "opentelemetry-instrumentation-vertexai>=0.36.0",
35
+ "opentelemetry-instrumentation-watsonx>=0.36.0",
36
+ "httpx>=0.27.2",
37
+ "pydantic>=2.10.3",
38
+ "typing-extensions>=4.12.2",
39
+ ]
40
+
41
+ [dependency-groups]
42
+ dev = [
43
+ "pytest-asyncio>=0.24.0",
44
+ "pytest-xdist>=3.6.1",
45
+ "pytest>=8.3.4",
46
+ "respx>=0.22.0",
47
+ "pyright>=1.1.392",
48
+ "ruff>=0.8.3",
49
+ "sh>=1.14.3",
50
+ ]
51
+
52
+ [tool.pyright]
53
+ pythonVersion = "3.9"
54
+ typeCheckingMode = "strict"
55
+ reportMissingTypeStubs = false
56
+ reportUnnecessaryIsInstance = false
57
+ reportPrivateUsage = false
58
+
59
+ [tool.ruff]
60
+ target-version = "py39"
61
+ line-length = 120
62
+ indent-width = 4
63
+
64
+ [tool.ruff.lint]
65
+ select = ["B", "C4", "E", "F", "I", "W", "UP"]
66
+ ignore = [
67
+ "F401",
68
+ "F403",
69
+ # Needed because unnecessary str() on field aliases are needed
70
+ # https://docs.pydantic.dev/2.8/concepts/fields/#field-aliases
71
+ "UP018",
72
+ # Needed because typing.List and typing.Dict are semi-deprecated
73
+ # in new Python versions but we want to maintain compatibility
74
+ "UP006",
75
+ "UP035",
76
+ ]
77
+
78
+ [tool.ruff.format]
79
+ quote-style = "double"
80
+ indent-style = "space"
81
+
82
+ [tool.pytest.ini_options]
83
+ addopts = "-p no:warnings -n auto"
84
+ xfail_strict = true
85
+ asyncio_mode = "auto"
86
+ asyncio_default_fixture_loop_scope = "function"
87
+
88
+ [build-system]
89
+ requires = ["hatchling"]
90
+ build-backend = "hatchling.build"
@@ -0,0 +1,8 @@
1
+ import sys
2
+
3
+ from sh import ruff # type: ignore
4
+
5
+ files = sys.argv[1:] or ["."]
6
+
7
+ ruff("check", "--fix", *files, _out=sys.stdout)
8
+ ruff("format", *files, _out=sys.stdout)
@@ -0,0 +1,9 @@
1
+ import sys
2
+
3
+ from sh import pyright, ruff # type: ignore
4
+
5
+ files = sys.argv[1:] or ["."]
6
+
7
+ pyright(*files, _out=sys.stdout)
8
+ ruff("check", *files, _out=sys.stdout)
9
+ ruff("format", "--check", *files, _out=sys.stdout)
@@ -0,0 +1,7 @@
1
+ import sys
2
+
3
+ from sh import pytest # type: ignore
4
+
5
+ files = sys.argv[1:] or ["."]
6
+
7
+ pytest(*files, _out=sys.stdout)
@@ -0,0 +1 @@
1
+ from .telemetry import *
@@ -0,0 +1 @@
1
+ from .env import *
@@ -0,0 +1,18 @@
1
+ from latitude_telemetry.util import Model, get_env
2
+
3
+ DEFAULT_GATEWAY_HOSTNAME = "gateway.latitude.so"
4
+ DEFAULT_GATEWAY_PORT = 443
5
+ DEFAULT_GATEWAY_SSL = True
6
+
7
+
8
+ class Env(Model):
9
+ GATEWAY_HOSTNAME: str
10
+ GATEWAY_PORT: int
11
+ GATEWAY_SSL: bool
12
+
13
+
14
+ env = Env(
15
+ GATEWAY_HOSTNAME=get_env("GATEWAY_HOSTNAME", DEFAULT_GATEWAY_HOSTNAME),
16
+ GATEWAY_PORT=get_env("GATEWAY_PORT", DEFAULT_GATEWAY_PORT),
17
+ GATEWAY_SSL=get_env("GATEWAY_SSL", DEFAULT_GATEWAY_SSL),
18
+ )
@@ -0,0 +1,2 @@
1
+ from .exporter import *
2
+ from .payloads import *
@@ -0,0 +1,172 @@
1
+ import time
2
+ from typing import Any, Dict, List, Sequence
3
+
4
+ import httpx
5
+ from opentelemetry.sdk import trace as otel
6
+ from opentelemetry.sdk.trace.export import SpanExporter, SpanExportResult
7
+ from opentelemetry.trace import format_span_id, format_trace_id
8
+
9
+ from latitude_telemetry.exporter.payloads import (
10
+ Attribute,
11
+ AttributeValue,
12
+ CreateTraceRequestBody,
13
+ Event,
14
+ Link,
15
+ Resource,
16
+ ResourceSpan,
17
+ ScopeSpan,
18
+ Span,
19
+ Status,
20
+ )
21
+ from latitude_telemetry.telemetry.types import GatewayOptions
22
+ from latitude_telemetry.util import Model
23
+
24
+ RETRIABLE_STATUSES = [408, 409, 429, 500, 502, 503, 504]
25
+
26
+
27
+ class ExporterOptions(Model):
28
+ api_key: str
29
+ gateway: GatewayOptions
30
+ retries: int
31
+ delay: float
32
+ timeout: float
33
+
34
+
35
+ class Exporter(SpanExporter):
36
+ _options: ExporterOptions
37
+
38
+ def __init__(self, options: ExporterOptions):
39
+ self._options = options
40
+
41
+ def export(self, spans: Sequence[otel.ReadableSpan]) -> SpanExportResult:
42
+ if not spans:
43
+ return SpanExportResult.SUCCESS
44
+
45
+ try:
46
+ self._send(self._serialize(list(spans)))
47
+
48
+ except Exception:
49
+ return SpanExportResult.FAILURE
50
+
51
+ return SpanExportResult.SUCCESS
52
+
53
+ def shutdown(self) -> None:
54
+ return None
55
+
56
+ def force_flush(self, timeout_millis: int = 30000) -> bool:
57
+ return True
58
+
59
+ def _serialize(self, spans: List[otel.ReadableSpan]) -> List[ResourceSpan]:
60
+ if not spans:
61
+ return []
62
+
63
+ return [
64
+ ResourceSpan(
65
+ resource=Resource(attributes=self._serialize_attributes(dict(spans[0].resource.attributes or {}))),
66
+ scope_spans=[
67
+ ScopeSpan(
68
+ spans=[
69
+ Span(
70
+ # Note: span.context should not be None
71
+ trace_id=format_trace_id(span.context.trace_id if span.context else 0),
72
+ # Note: span.context should not be None
73
+ span_id=format_span_id(span.context.span_id if span.context else 0),
74
+ parent_span_id=format_span_id(span.parent.span_id) if span.parent else None,
75
+ name=span.name,
76
+ kind=span.kind.value,
77
+ # Note: span.start_time should not be None
78
+ start_time=str(span.start_time or 0),
79
+ end_time=str(span.end_time) if span.end_time else None,
80
+ status=Status(
81
+ code=span.status.status_code.value,
82
+ message=span.status.description,
83
+ ),
84
+ events=[
85
+ Event(
86
+ name=event.name,
87
+ time=str(event.timestamp),
88
+ attributes=self._serialize_attributes(dict(event.attributes or {})),
89
+ )
90
+ for event in span.events
91
+ ],
92
+ links=[
93
+ Link(
94
+ trace_id=format_trace_id(link.context.trace_id),
95
+ span_id=format_span_id(link.context.span_id),
96
+ attributes=self._serialize_attributes(dict(link.attributes or {})),
97
+ )
98
+ for link in span.links
99
+ ],
100
+ attributes=self._serialize_attributes(dict(span.attributes or {})),
101
+ )
102
+ for span in spans
103
+ ]
104
+ )
105
+ ],
106
+ )
107
+ ]
108
+
109
+ def _serialize_attributes(self, attributes: Dict[str, Any]) -> List[Attribute]:
110
+ serialized_attributes: List[Attribute] = []
111
+
112
+ for key, value in attributes.items():
113
+ serialized_value = AttributeValue(string=str(value))
114
+
115
+ if isinstance(value, str):
116
+ serialized_value = AttributeValue(string=value)
117
+
118
+ elif isinstance(value, bool):
119
+ serialized_value = AttributeValue(boolean=value)
120
+
121
+ elif isinstance(value, int):
122
+ serialized_value = AttributeValue(integer=value)
123
+
124
+ elif isinstance(value, float):
125
+ serialized_value = AttributeValue(integer=int(value))
126
+
127
+ serialized_attributes.append(Attribute(key=key, value=serialized_value))
128
+
129
+ return serialized_attributes
130
+
131
+ def _send(self, spans: List[ResourceSpan]) -> None:
132
+ client = httpx.Client(
133
+ headers={
134
+ "Authorization": f"Bearer {self._options.api_key}",
135
+ "Content-Type": "application/json",
136
+ },
137
+ timeout=self._options.timeout,
138
+ follow_redirects=False,
139
+ max_redirects=0,
140
+ )
141
+ response = None
142
+ attempt = 1
143
+
144
+ try:
145
+ method = "POST"
146
+ url = f"{self._options.gateway.base_url}/otlp/v1/traces"
147
+ content = CreateTraceRequestBody(resource_spans=spans).model_dump_json()
148
+
149
+ while attempt <= self._options.retries:
150
+ try:
151
+ response = client.request(method=method, url=url, content=content)
152
+ response.raise_for_status()
153
+
154
+ break
155
+
156
+ except Exception as exception:
157
+ if attempt >= self._options.retries:
158
+ raise exception
159
+
160
+ if response and response.status_code in RETRIABLE_STATUSES:
161
+ time.sleep(self._options.delay * (2 ** (attempt - 1)))
162
+ else:
163
+ raise exception
164
+
165
+ finally:
166
+ if response:
167
+ response.close()
168
+
169
+ attempt += 1
170
+
171
+ finally:
172
+ client.close()
@@ -0,0 +1,62 @@
1
+ from typing import List, Optional
2
+
3
+ from latitude_telemetry.util import Field, Model
4
+
5
+
6
+ class AttributeValue(Model):
7
+ string: Optional[str] = Field(default=None, alias=str("stringValue"))
8
+ integer: Optional[int] = Field(default=None, alias=str("intValue"))
9
+ boolean: Optional[bool] = Field(default=None, alias=str("boolValue"))
10
+
11
+
12
+ class Attribute(Model):
13
+ key: str
14
+ value: AttributeValue
15
+
16
+
17
+ class Resource(Model):
18
+ attributes: List[Attribute]
19
+
20
+
21
+ class Status(Model):
22
+ code: int
23
+ message: Optional[str] = None
24
+
25
+
26
+ class Event(Model):
27
+ name: str
28
+ time: str = Field(alias=str("timeUnixNano"))
29
+ attributes: Optional[List[Attribute]] = None
30
+
31
+
32
+ class Link(Model):
33
+ trace_id: str = Field(alias=str("traceId"))
34
+ span_id: str = Field(alias=str("spanId"))
35
+ attributes: Optional[List[Attribute]] = None
36
+
37
+
38
+ class Span(Model):
39
+ trace_id: str = Field(alias=str("traceId"))
40
+ span_id: str = Field(alias=str("spanId"))
41
+ parent_span_id: Optional[str] = Field(default=None, alias=str("parentSpanId"))
42
+ name: str
43
+ kind: int
44
+ start_time: str = Field(alias=str("startTimeUnixNano"))
45
+ end_time: Optional[str] = Field(default=None, alias=str("endTimeUnixNano"))
46
+ status: Optional[Status] = None
47
+ events: Optional[List[Event]] = None
48
+ links: Optional[List[Link]] = None
49
+ attributes: Optional[List[Attribute]] = None
50
+
51
+
52
+ class ScopeSpan(Model):
53
+ spans: List[Span]
54
+
55
+
56
+ class ResourceSpan(Model):
57
+ resource: Resource
58
+ scope_spans: List[ScopeSpan] = Field(alias=str("scopeSpans"))
59
+
60
+
61
+ class CreateTraceRequestBody(Model):
62
+ resource_spans: List[ResourceSpan] = Field(alias=str("resourceSpans"))
@@ -0,0 +1,2 @@
1
+ from .telemetry import *
2
+ from .types import *