|
27 | 27 |
|
28 | 28 |
|
29 | 29 | def encode_spans(spans: Sequence[ReadableSpan]) -> bytes: |
30 | | - spans = sorted(spans, key=lambda s: (id(s.resource), id(s.instrumentation_scope))) |
| 30 | + resource_cache: dict[Resource, tuple] = {} |
| 31 | + scope_cache: dict[InstrumentationScope, tuple] = {} |
| 32 | + |
| 33 | + def linearise(span: ReadableSpan): |
| 34 | + r = span.resource |
| 35 | + if r not in resource_cache: |
| 36 | + resource_cache[r] = (r.schema_url, tuple(r.attributes.items())) |
| 37 | + s = span.instrumentation_scope |
| 38 | + assert s |
| 39 | + assert s.attributes is not None |
| 40 | + if s not in scope_cache: |
| 41 | + scope_cache[s] = ( |
| 42 | + s.schema_url, |
| 43 | + s.name, |
| 44 | + s.version, |
| 45 | + tuple(s.attributes.items()), |
| 46 | + ) |
| 47 | + return (resource_cache[r], scope_cache[s]) |
| 48 | + |
| 49 | + spans = sorted(spans, key=linearise) |
31 | 50 | rv = {"resourceSpans": []} |
32 | | - last_rs = last_is = None |
| 51 | + last_resource = last_scope = None |
33 | 52 | for span in spans: |
34 | 53 | assert span.resource |
35 | 54 | assert span.instrumentation_scope |
36 | | - if span.resource is not last_rs: |
37 | | - last_rs = span.resource |
38 | | - last_is = None |
| 55 | + if span.resource != last_resource: |
| 56 | + last_resource = span.resource |
| 57 | + last_scope = None |
39 | 58 | rv["resourceSpans"].append( |
40 | 59 | { |
41 | 60 | "resource": _resource(span.resource), |
42 | 61 | "scopeSpans": [], |
43 | 62 | } |
44 | 63 | ) |
45 | | - if span.instrumentation_scope is not last_is: |
46 | | - last_is = span.instrumentation_scope |
| 64 | + if span.instrumentation_scope != last_scope: |
| 65 | + last_scope = span.instrumentation_scope |
47 | 66 | rv["resourceSpans"][-1]["scopeSpans"].append( |
48 | 67 | { |
49 | 68 | "scope": _scope(span.instrumentation_scope), |
@@ -111,7 +130,10 @@ def _value(v: _VALUE) -> dict[str, Any]: |
111 | 130 | def _scope(scope: InstrumentationScope): |
112 | 131 | rv = { |
113 | 132 | "name": scope.name, |
114 | | - **_attributes(scope), |
| 133 | + # Upstream code for attrs and schema has landed, but wasn't released yet |
| 134 | + # https://github.com/open-telemetry/opentelemetry-python/pull/4359 |
| 135 | + # "schema_url": scope.schema_url, # check if it may be null |
| 136 | + # **_attributes(scope), |
115 | 137 | } |
116 | 138 | if scope.version: |
117 | 139 | rv["version"] = scope.version |
@@ -160,8 +182,10 @@ def _span_id(span_id: int) -> str: |
160 | 182 |
|
161 | 183 | def _status(status: Status) -> dict[str, Any]: |
162 | 184 | rv = {} |
163 | | - # rv["code"] ... |
164 | | - # rv["message"] = ... |
| 185 | + if status.status_code.value: |
| 186 | + rv["code"] = status.status_code.value |
| 187 | + if status.description: |
| 188 | + rv["message"] = status.description |
165 | 189 | return rv |
166 | 190 |
|
167 | 191 |
|
|
0 commit comments