63
63
import typing
64
64
from json import dumps
65
65
from os import environ
66
+ from types import ModuleType
67
+ from typing import List , Optional
66
68
from urllib import parse
67
69
68
70
from opentelemetry .attributes import BoundedAttributes
75
77
from opentelemetry .util ._importlib_metadata import entry_points , version
76
78
from opentelemetry .util .types import AttributeValue
77
79
80
+ psutil : Optional [ModuleType ] = None
81
+
78
82
try :
79
- import psutil
83
+ import psutil as pustil_module
84
+
85
+ pustil = pustil_module
80
86
except ImportError :
81
- psutil = None
87
+ pass
82
88
83
89
LabelValue = AttributeValue
84
90
Attributes = typing .Mapping [str , LabelValue ]
141
147
TELEMETRY_AUTO_VERSION = ResourceAttributes .TELEMETRY_AUTO_VERSION
142
148
TELEMETRY_SDK_LANGUAGE = ResourceAttributes .TELEMETRY_SDK_LANGUAGE
143
149
144
- _OPENTELEMETRY_SDK_VERSION = version ("opentelemetry-sdk" )
150
+ _OPENTELEMETRY_SDK_VERSION : str = version ("opentelemetry-sdk" )
145
151
146
152
147
153
class Resource :
148
154
"""A Resource is an immutable representation of the entity producing telemetry as Attributes."""
149
155
156
+ _attributes : BoundedAttributes
157
+ _schema_url : str
158
+
150
159
def __init__ (
151
160
self , attributes : Attributes , schema_url : typing .Optional [str ] = None
152
161
):
@@ -173,7 +182,7 @@ def create(
173
182
if not attributes :
174
183
attributes = {}
175
184
176
- resource_detectors = []
185
+ resource_detectors : List [ ResourceDetector ] = []
177
186
178
187
resource = _DEFAULT_RESOURCE
179
188
@@ -182,20 +191,21 @@ def create(
182
191
).split ("," )
183
192
184
193
if "otel" not in otel_experimental_resource_detectors :
194
+
185
195
otel_experimental_resource_detectors .append ("otel" )
186
196
197
+ resource_detector : str
187
198
for resource_detector in otel_experimental_resource_detectors :
188
199
resource_detectors .append (
189
200
next (
190
201
iter (
191
202
entry_points (
192
203
group = "opentelemetry_resource_detector" ,
193
204
name = resource_detector .strip (),
194
- )
205
+ ) # type: ignore
195
206
)
196
- ). load ()()
207
+ )
197
208
)
198
-
199
209
resource = get_aggregated_resources (
200
210
resource_detectors , _DEFAULT_RESOURCE
201
211
).merge (Resource (attributes , schema_url ))
@@ -206,7 +216,7 @@ def create(
206
216
PROCESS_EXECUTABLE_NAME , None
207
217
)
208
218
if process_executable_name :
209
- default_service_name += ":" + process_executable_name
219
+ default_service_name += ":" + str ( process_executable_name )
210
220
resource = resource .merge (
211
221
Resource ({SERVICE_NAME : default_service_name }, schema_url )
212
222
)
@@ -218,6 +228,8 @@ def get_empty() -> "Resource":
218
228
219
229
@property
220
230
def attributes (self ) -> Attributes :
231
+ if self ._attributes is None :
232
+ raise ValueError ("Attributes are not set." )
221
233
return self ._attributes
222
234
223
235
@property
@@ -241,7 +253,7 @@ def merge(self, other: "Resource") -> "Resource":
241
253
Returns:
242
254
The newly-created Resource.
243
255
"""
244
- merged_attributes = self .attributes . copy ( )
256
+ merged_attributes = dict ( self .attributes )
245
257
merged_attributes .update (other .attributes )
246
258
247
259
if self .schema_url == "" :
@@ -257,7 +269,6 @@ def merge(self, other: "Resource") -> "Resource":
257
269
other .schema_url ,
258
270
)
259
271
return self
260
-
261
272
return Resource (merged_attributes , schema_url )
262
273
263
274
def __eq__ (self , other : object ) -> bool :
@@ -268,15 +279,15 @@ def __eq__(self, other: object) -> bool:
268
279
and self ._schema_url == other ._schema_url
269
280
)
270
281
271
- def __hash__ (self ):
272
- return hash (
273
- f"{ dumps (self ._attributes .copy (), sort_keys = True )} |{ self ._schema_url } "
274
- )
282
+ def __hash__ (self ) -> int :
283
+ attributes_json = dumps (self ._attributes .copy (), sort_keys = True ) # type: ignore
284
+ return hash (f"{ attributes_json } |{ self ._schema_url } " )
275
285
276
- def to_json (self , indent = 4 ) -> str :
286
+ def to_json (self , indent : int = 4 ) -> str :
287
+ attributes = dict (self ._attributes ) # type: ignore
277
288
return dumps (
278
289
{
279
- "attributes" : dict ( self . _attributes ),
290
+ "attributes" : attributes , # type: ignore
280
291
"schema_url" : self ._schema_url ,
281
292
},
282
293
indent = indent ,
@@ -294,7 +305,7 @@ def to_json(self, indent=4) -> str:
294
305
295
306
296
307
class ResourceDetector (abc .ABC ):
297
- def __init__ (self , raise_on_error = False ):
308
+ def __init__ (self , raise_on_error : bool = False ) -> None :
298
309
self .raise_on_error = raise_on_error
299
310
300
311
@abc .abstractmethod
@@ -343,7 +354,7 @@ def detect(self) -> "Resource":
343
354
),
344
355
)
345
356
)
346
- _process_pid = os .getpid ()
357
+ _process_pid = str ( os .getpid () )
347
358
_process_executable_name = sys .executable
348
359
_process_executable_path = os .path .dirname (_process_executable_name )
349
360
_process_command = sys .argv [0 ]
@@ -358,23 +369,24 @@ def detect(self) -> "Resource":
358
369
PROCESS_EXECUTABLE_PATH : _process_executable_path ,
359
370
PROCESS_COMMAND : _process_command ,
360
371
PROCESS_COMMAND_LINE : _process_command_line ,
361
- PROCESS_COMMAND_ARGS : _process_command_args ,
372
+ PROCESS_COMMAND_ARGS : "" . join ( _process_command_args ) ,
362
373
}
363
374
if hasattr (os , "getppid" ):
364
375
# pypy3 does not have getppid()
365
- resource_info [PROCESS_PARENT_PID ] = os .getppid ()
376
+ resource_info [PROCESS_PARENT_PID ] = str ( os .getppid () )
366
377
367
378
if psutil is not None :
368
- process = psutil .Process ()
369
- resource_info [PROCESS_OWNER ] = process .username ()
379
+ process : pustil_module .Process = psutil .Process ()
380
+ username = process .username ()
381
+ resource_info [PROCESS_OWNER ] = username
370
382
371
383
return Resource (resource_info )
372
384
373
385
374
386
def get_aggregated_resources (
375
387
detectors : typing .List ["ResourceDetector" ],
376
388
initial_resource : typing .Optional [Resource ] = None ,
377
- timeout = 5 ,
389
+ timeout : int = 5 ,
378
390
) -> "Resource" :
379
391
"""Retrieves resources from detectors in the order that they were passed
380
392
0 commit comments