1414#
1515# This file has been modified from the original source code at
1616#
17- # https://github.com/open-telemetry/opentelemetry-python/tree/v1.26 .0
17+ # https://github.com/open-telemetry/opentelemetry-python/tree/v1.35 .0
1818#
1919# by Snowflake Inc.
2020
2121
22+ from __future__ import annotations
23+
2224import logging
2325from collections .abc import Sequence
24- from itertools import count
2526from typing import (
2627 Any ,
28+ Callable ,
29+ Dict ,
30+ List ,
2731 Mapping ,
2832 Optional ,
29- List ,
30- Callable ,
3133 TypeVar ,
32- Dict ,
33- Iterator ,
3434)
3535
36- from opentelemetry .sdk . util . instrumentation import InstrumentationScope
36+ from snowflake . telemetry . _internal . opentelemetry .proto . common . v1 . common_marshaler import AnyValue as PB2AnyValue
3737from snowflake .telemetry ._internal .opentelemetry .proto .common .v1 .common_marshaler import (
38- InstrumentationScope as PB2InstrumentationScope ,
38+ ArrayValue as PB2ArrayValue ,
3939)
40- from snowflake .telemetry ._internal .opentelemetry .proto .resource .v1 .resource_marshaler import (
41- Resource as PB2Resource ,
40+ from snowflake .telemetry ._internal .opentelemetry .proto .common .v1 .common_marshaler import (
41+ InstrumentationScope as PB2InstrumentationScope ,
4242)
43- from snowflake .telemetry ._internal .opentelemetry .proto .common .v1 .common_marshaler import AnyValue as PB2AnyValue
4443from snowflake .telemetry ._internal .opentelemetry .proto .common .v1 .common_marshaler import KeyValue as PB2KeyValue
4544from snowflake .telemetry ._internal .opentelemetry .proto .common .v1 .common_marshaler import (
4645 KeyValueList as PB2KeyValueList ,
4746)
48- from snowflake .telemetry ._internal .opentelemetry .proto .common .v1 .common_marshaler import (
49- ArrayValue as PB2ArrayValue ,
47+ from snowflake .telemetry ._internal .opentelemetry .proto .resource .v1 .resource_marshaler import (
48+ Resource as PB2Resource ,
5049)
5150from opentelemetry .sdk .trace import Resource
52- from opentelemetry .util .types import Attributes
51+ from opentelemetry .sdk .util .instrumentation import InstrumentationScope
52+ from opentelemetry .util .types import _ExtendedAttributes
5353
5454_logger = logging .getLogger (__name__ )
5555
@@ -65,14 +65,19 @@ def _encode_instrumentation_scope(
6565 return PB2InstrumentationScope (
6666 name = instrumentation_scope .name ,
6767 version = instrumentation_scope .version ,
68+ attributes = _encode_attributes (instrumentation_scope .attributes ),
6869 )
6970
7071
7172def _encode_resource (resource : Resource ) -> PB2Resource :
7273 return PB2Resource (attributes = _encode_attributes (resource .attributes ))
7374
7475
75- def _encode_value (value : Any ) -> PB2AnyValue :
76+ def _encode_value (
77+ value : Any , allow_null : bool = False
78+ ) -> Optional [PB2AnyValue ]:
79+ if allow_null is True and value is None :
80+ return None
7681 if isinstance (value , bool ):
7782 return PB2AnyValue (bool_value = value )
7883 if isinstance (value , str ):
@@ -81,21 +86,49 @@ def _encode_value(value: Any) -> PB2AnyValue:
8186 return PB2AnyValue (int_value = value )
8287 if isinstance (value , float ):
8388 return PB2AnyValue (double_value = value )
89+ if isinstance (value , bytes ):
90+ return PB2AnyValue (bytes_value = value )
8491 if isinstance (value , Sequence ):
8592 return PB2AnyValue (
86- array_value = PB2ArrayValue (values = [_encode_value (v ) for v in value ])
93+ array_value = PB2ArrayValue (
94+ values = _encode_array (value , allow_null = allow_null )
95+ )
8796 )
8897 elif isinstance (value , Mapping ):
8998 return PB2AnyValue (
9099 kvlist_value = PB2KeyValueList (
91- values = [_encode_key_value (str (k ), v ) for k , v in value .items ()]
100+ values = [
101+ _encode_key_value (str (k ), v , allow_null = allow_null )
102+ for k , v in value .items ()
103+ ]
92104 )
93105 )
94106 raise Exception (f"Invalid type { type (value )} of value { value } " )
95107
96108
97- def _encode_key_value (key : str , value : Any ) -> PB2KeyValue :
98- return PB2KeyValue (key = key , value = _encode_value (value ))
109+ def _encode_key_value (
110+ key : str , value : Any , allow_null : bool = False
111+ ) -> PB2KeyValue :
112+ return PB2KeyValue (
113+ key = key , value = _encode_value (value , allow_null = allow_null )
114+ )
115+
116+
117+ def _encode_array (
118+ array : Sequence [Any ], allow_null : bool = False
119+ ) -> Sequence [PB2AnyValue ]:
120+ if not allow_null :
121+ # Let the exception get raised by _encode_value()
122+ return [_encode_value (v , allow_null = allow_null ) for v in array ]
123+
124+ return [
125+ _encode_value (v , allow_null = allow_null )
126+ if v is not None
127+ # Use an empty AnyValue to represent None in an array. Behavior may change pending
128+ # https://github.com/open-telemetry/opentelemetry-specification/issues/4392
129+ else PB2AnyValue ()
130+ for v in array
131+ ]
99132
100133
101134def _encode_span_id (span_id : int ) -> bytes :
@@ -107,14 +140,17 @@ def _encode_trace_id(trace_id: int) -> bytes:
107140
108141
109142def _encode_attributes (
110- attributes : Attributes ,
143+ attributes : _ExtendedAttributes ,
144+ allow_null : bool = False ,
111145) -> Optional [List [PB2KeyValue ]]:
112146 if attributes :
113147 pb2_attributes = []
114148 for key , value in attributes .items ():
115149 # pylint: disable=broad-exception-caught
116150 try :
117- pb2_attributes .append (_encode_key_value (key , value ))
151+ pb2_attributes .append (
152+ _encode_key_value (key , value , allow_null = allow_null )
153+ )
118154 except Exception as error :
119155 _logger .exception ("Failed to encode key %s: %s" , key , error )
120156 else :
@@ -145,38 +181,3 @@ def _get_resource_data(
145181 )
146182 )
147183 return resource_data
148-
149-
150- def _create_exp_backoff_generator (max_value : int = 0 ) -> Iterator [int ]:
151- """
152- Generates an infinite sequence of exponential backoff values. The sequence starts
153- from 1 (2^0) and doubles each time (2^1, 2^2, 2^3, ...). If a max_value is specified
154- and non-zero, the generated values will not exceed this maximum, capping at max_value
155- instead of growing indefinitely.
156-
157- Parameters:
158- - max_value (int, optional): The maximum value to yield. If 0 or not provided, the
159- sequence grows without bound.
160-
161- Returns:
162- Iterator[int]: An iterator that yields the exponential backoff values, either uncapped or
163- capped at max_value.
164-
165- Example:
166- ```
167- gen = _create_exp_backoff_generator(max_value=10)
168- for _ in range(5):
169- print(next(gen))
170- ```
171- This will print:
172- 1
173- 2
174- 4
175- 8
176- 10
177-
178- Note: this functionality used to be handled by the 'backoff' package.
179- """
180- for i in count (0 ):
181- out = 2 ** i
182- yield min (out , max_value ) if max_value else out
0 commit comments