Skip to content

Commit 0b3ece0

Browse files
committed
Changed MetricsTracer to have its own setters for attributes
1 parent 5002654 commit 0b3ece0

File tree

4 files changed

+302
-39
lines changed

4 files changed

+302
-39
lines changed

google/cloud/spanner_v1/metrics/metrics_exporter.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@
6262
from opentelemetry.sdk.resources import Resource
6363

6464
HAS_OPENTELEMETRY_INSTALLED = True
65-
except ImportError:
65+
except ImportError: # pragma: NO COVER
6666
HAS_OPENTELEMETRY_INSTALLED = False
6767

6868
try:

google/cloud/spanner_v1/metrics/metrics_tracer.py

Lines changed: 201 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,18 @@
2424
from typing import Dict
2525
from grpc import StatusCode
2626
from .constants import (
27-
METRIC_LABEL_KEY_STATUS,
28-
METRIC_LABEL_KEY_METHOD,
27+
METRIC_LABEL_KEY_CLIENT_NAME,
28+
METRIC_LABEL_KEY_CLIENT_UID,
29+
METRIC_LABEL_KEY_DATABASE,
2930
METRIC_LABEL_KEY_DIRECT_PATH_ENABLED,
3031
METRIC_LABEL_KEY_DIRECT_PATH_USED,
32+
METRIC_LABEL_KEY_METHOD,
33+
METRIC_LABEL_KEY_STATUS,
34+
MONITORED_RES_LABEL_KEY_CLIENT_HASH,
35+
MONITORED_RES_LABEL_KEY_INSTANCE,
36+
MONITORED_RES_LABEL_KEY_INSTANCE_CONFIG,
37+
MONITORED_RES_LABEL_KEY_LOCATION,
38+
MONITORED_RES_LABEL_KEY_PROJECT,
3139
)
3240

3341
try:
@@ -107,23 +115,62 @@ def __init__(self, is_direct_path_enabled: bool = False):
107115

108116
@property
109117
def attempt_count(self):
118+
"""
119+
Getter method for the attempt_count property.
120+
121+
This method returns the current count of attempts made for the metric operation.
122+
123+
Returns:
124+
int: The current count of attempts.
125+
"""
110126
return self._attempt_count
111127

112128
@property
113129
def current_attempt(self):
130+
"""
131+
Getter method for the current_attempt property.
132+
133+
This method returns the current MetricAttemptTracer instance associated with the metric operation.
134+
135+
Returns:
136+
MetricAttemptTracer: The current MetricAttemptTracer instance.
137+
"""
114138
return self._current_attempt
115139

116140
@property
117141
def start_time(self):
142+
"""
143+
Getter method for the start_time property.
144+
145+
This method returns the start time of the metric operation.
146+
147+
Returns:
148+
datetime: The start time of the metric operation.
149+
"""
118150
return self._start_time
119151

120152
def increment_attempt_count(self):
153+
"""
154+
Increments the attempt count by 1.
155+
156+
This method updates the attempt count by incrementing it by 1, indicating a new attempt has been made.
157+
"""
121158
self._attempt_count += 1
122159

123160
def start(self):
161+
"""
162+
Sets the start time of the metric operation to the current time.
163+
164+
This method updates the start time of the metric operation to the current time, indicating the operation has started.
165+
"""
124166
self._start_time = datetime.now()
125167

126168
def new_attempt(self):
169+
"""
170+
Initializes a new MetricAttemptTracer instance for the current metric operation.
171+
172+
This method sets up a new MetricAttemptTracer instance, indicating a new attempt is being made within the metric operation.
173+
"""
127174
self._current_attempt = MetricAttemptTracer()
128175

129176

@@ -181,10 +228,29 @@ def __init__(
181228
self._instrument_operation_counter = instrument_operation_counter
182229
self.enabled = enabled
183230

231+
@staticmethod
232+
def _get_ms_time_diff(start: datetime, end: datetime) -> float:
233+
"""
234+
Calculate the time difference in milliseconds between two datetime objects.
235+
236+
This method calculates the time difference between two datetime objects and returns the result in milliseconds.
237+
This is useful for measuring the duration of operations or attempts for metrics tracing.
238+
Note: total_seconds() returns a float value of seconds.
239+
240+
Args:
241+
start (datetime): The start datetime.
242+
end (datetime): The end datetime.
243+
244+
Returns:
245+
float: The time difference in milliseconds.
246+
"""
247+
time_delta = end - start
248+
return time_delta.total_seconds() * 1000
249+
184250
@property
185251
def client_attributes(self) -> Dict[str, str]:
186252
"""
187-
Returns a dictionary of client attributes used for metrics tracing.
253+
Return a dictionary of client attributes used for metrics tracing.
188254
189255
This property returns a dictionary containing client attributes such as project, instance,
190256
instance configuration, location, client hash, client UID, client name, and database.
@@ -198,7 +264,7 @@ def client_attributes(self) -> Dict[str, str]:
198264
@property
199265
def instrument_attempt_counter(self) -> Counter:
200266
"""
201-
Returns the instrument for counting attempts.
267+
Return the instrument for counting attempts.
202268
203269
This property returns the Counter instrument used to count the number of attempts made during RPC operations.
204270
This metric is useful for tracking the frequency of attempts and can help identify patterns or issues in the operation flow.
@@ -211,7 +277,7 @@ def instrument_attempt_counter(self) -> Counter:
211277
@property
212278
def instrument_attempt_latency(self) -> Histogram:
213279
"""
214-
Returns the instrument for measuring attempt latency.
280+
Return the instrument for measuring attempt latency.
215281
216282
This property returns the Histogram instrument used to measure the latency of individual attempts.
217283
This metric is useful for tracking the performance of attempts and can help identify bottlenecks or issues in the operation flow.
@@ -224,7 +290,7 @@ def instrument_attempt_latency(self) -> Histogram:
224290
@property
225291
def instrument_operation_counter(self) -> Counter:
226292
"""
227-
Returns the instrument for counting operations.
293+
Return the instrument for counting operations.
228294
229295
This property returns the Counter instrument used to count the number of operations made during RPC operations.
230296
This metric is useful for tracking the frequency of operations and can help identify patterns or issues in the operation flow.
@@ -237,7 +303,7 @@ def instrument_operation_counter(self) -> Counter:
237303
@property
238304
def instrument_operation_latency(self) -> Histogram:
239305
"""
240-
Returns the instrument for measuring operation latency.
306+
Return the instrument for measuring operation latency.
241307
242308
This property returns the Histogram instrument used to measure the latency of operations.
243309
This metric is useful for tracking the performance of operations and can help identify bottlenecks or issues in the operation flow.
@@ -249,7 +315,7 @@ def instrument_operation_latency(self) -> Histogram:
249315

250316
def record_attempt_start(self) -> None:
251317
"""
252-
Records the start of a new attempt within the current operation.
318+
Record the start of a new attempt within the current operation.
253319
254320
This method increments the attempt count for the current operation and marks the start of a new attempt.
255321
It is used to track the number of attempts made during an operation and to identify the start of each attempt for metrics and tracing purposes.
@@ -259,7 +325,7 @@ def record_attempt_start(self) -> None:
259325

260326
def record_attempt_completion(self, status: str = StatusCode.OK.name) -> None:
261327
"""
262-
Records the completion of an attempt within the current operation.
328+
Record the completion of an attempt within the current operation.
263329
264330
This method updates the status of the current attempt to indicate its completion and records the latency of the attempt.
265331
It calculates the elapsed time since the attempt started and uses this value to record the attempt latency metric.
@@ -308,7 +374,6 @@ def record_operation_completion(self) -> None:
308374
if not self.enabled:
309375
return
310376
end_time = datetime.now()
311-
312377
# Build Attributes
313378
operation_attributes = self._create_operation_otel_attributes()
314379
attempt_attributes = self._create_attempt_otel_attributes()
@@ -345,17 +410,16 @@ def _create_otel_attributes(self) -> Dict[str, str]:
345410
if not self.enabled:
346411
return
347412

348-
attributes = self.client_attributes.copy()
349-
attributes[METRIC_LABEL_KEY_METHOD] = self.method
350-
attributes[METRIC_LABEL_KEY_DIRECT_PATH_ENABLED] = str(
413+
self.client_attributes[METRIC_LABEL_KEY_METHOD] = self.method
414+
self.client_attributes[METRIC_LABEL_KEY_DIRECT_PATH_ENABLED] = str(
351415
self.current_op.direct_path_enabled
352416
)
353417
if self.current_op.current_attempt is not None:
354-
attributes[METRIC_LABEL_KEY_DIRECT_PATH_USED] = str(
418+
self.client_attributes[METRIC_LABEL_KEY_DIRECT_PATH_USED] = str(
355419
self.current_op.current_attempt.direct_path_used
356420
)
357421

358-
return attributes
422+
return self.client_attributes
359423

360424
def _create_operation_otel_attributes(self) -> Dict[str, str]:
361425
"""
@@ -395,21 +459,130 @@ def _create_attempt_otel_attributes(self) -> Dict[str, str]:
395459

396460
return attributes
397461

398-
@staticmethod
399-
def _get_ms_time_diff(start: datetime, end: datetime) -> float:
462+
def set_project(self, project: str) -> "MetricsTracer":
400463
"""
401-
Calculate the time difference in milliseconds between two datetime objects.
464+
Set the project attribute for metrics tracing.
402465
403-
This method calculates the time difference between two datetime objects and returns the result in milliseconds.
404-
This is useful for measuring the duration of operations or attempts for metrics tracing.
405-
Note: total_seconds() returns a float value of seconds.
466+
This method updates the project attribute in the client attributes dictionary for metrics tracing purposes.
467+
If the project attribute already has a value, this method does nothing and returns.
406468
407-
Args:
408-
start (datetime): The start datetime.
409-
end (datetime): The end datetime.
469+
:param project: The project name to set.
470+
:return: This instance of MetricsTracer for method chaining.
471+
"""
472+
if MONITORED_RES_LABEL_KEY_PROJECT not in self._client_attributes:
473+
self._client_attributes[MONITORED_RES_LABEL_KEY_PROJECT] = project
474+
return self
410475

411-
Returns:
412-
float: The time difference in milliseconds.
476+
def set_instance(self, instance: str) -> "MetricsTracer":
413477
"""
414-
time_delta = end - start
415-
return time_delta.total_seconds() * 1000
478+
Set the instance attribute for metrics tracing.
479+
480+
This method updates the instance attribute in the client attributes dictionary for metrics tracing purposes.
481+
If the instance attribute already has a value, this method does nothing and returns.
482+
483+
:param instance: The instance name to set.
484+
:return: This instance of MetricsTracer for method chaining.
485+
"""
486+
if MONITORED_RES_LABEL_KEY_INSTANCE not in self._client_attributes:
487+
self._client_attributes[MONITORED_RES_LABEL_KEY_INSTANCE] = instance
488+
return self
489+
490+
def set_instance_config(self, instance_config: str) -> "MetricsTracer":
491+
"""
492+
Set the instance configuration attribute for metrics tracing.
493+
494+
This method updates the instance configuration attribute in the client attributes dictionary for metrics tracing purposes.
495+
If the instance configuration attribute already has a value, this method does nothing and returns.
496+
497+
:param instance_config: The instance configuration name to set.
498+
:return: This instance of MetricsTracer for method chaining.
499+
"""
500+
if MONITORED_RES_LABEL_KEY_INSTANCE_CONFIG not in self._client_attributes:
501+
self._client_attributes[
502+
MONITORED_RES_LABEL_KEY_INSTANCE_CONFIG
503+
] = instance_config
504+
return self
505+
506+
def set_location(self, location: str) -> "MetricsTracer":
507+
"""
508+
Set the location attribute for metrics tracing.
509+
510+
This method updates the location attribute in the client attributes dictionary for metrics tracing purposes.
511+
If the location attribute already has a value, this method does nothing and returns.
512+
513+
:param location: The location name to set.
514+
:return: This instance of MetricsTracer for method chaining.
515+
"""
516+
if MONITORED_RES_LABEL_KEY_LOCATION not in self._client_attributes:
517+
self._client_attributes[MONITORED_RES_LABEL_KEY_LOCATION] = location
518+
return self
519+
520+
def set_client_hash(self, hash: str) -> "MetricsTracer":
521+
"""
522+
Set the client hash attribute for metrics tracing.
523+
524+
This method updates the client hash attribute in the client attributes dictionary for metrics tracing purposes.
525+
If the client hash attribute already has a value, this method does nothing and returns.
526+
527+
:param hash: The client hash to set.
528+
:return: This instance of MetricsTracer for method chaining.
529+
"""
530+
if MONITORED_RES_LABEL_KEY_CLIENT_HASH not in self._client_attributes:
531+
self._client_attributes[MONITORED_RES_LABEL_KEY_CLIENT_HASH] = hash
532+
return self
533+
534+
def set_client_uid(self, client_uid: str) -> "MetricsTracer":
535+
"""
536+
Set the client UID attribute for metrics tracing.
537+
538+
This method updates the client UID attribute in the client attributes dictionary for metrics tracing purposes.
539+
If the client UID attribute already has a value, this method does nothing and returns.
540+
541+
:param client_uid: The client UID to set.
542+
:return: This instance of MetricsTracer for method chaining.
543+
"""
544+
if METRIC_LABEL_KEY_CLIENT_UID not in self._client_attributes:
545+
self._client_attributes[METRIC_LABEL_KEY_CLIENT_UID] = client_uid
546+
return self
547+
548+
def set_client_name(self, client_name: str) -> "MetricsTracer":
549+
"""
550+
Set the client name attribute for metrics tracing.
551+
552+
This method updates the client name attribute in the client attributes dictionary for metrics tracing purposes.
553+
If the client name attribute already has a value, this method does nothing and returns.
554+
555+
:param client_name: The client name to set.
556+
:return: This instance of MetricsTracer for method chaining.
557+
"""
558+
if METRIC_LABEL_KEY_CLIENT_NAME not in self._client_attributes:
559+
self._client_attributes[METRIC_LABEL_KEY_CLIENT_NAME] = client_name
560+
return self
561+
562+
def set_database(self, database: str) -> "MetricsTracer":
563+
"""
564+
Set the database attribute for metrics tracing.
565+
566+
This method updates the database attribute in the client attributes dictionary for metrics tracing purposes.
567+
If the database attribute already has a value, this method does nothing and returns.
568+
569+
:param database: The database name to set.
570+
:return: This instance of MetricsTracer for method chaining.
571+
"""
572+
if METRIC_LABEL_KEY_DATABASE not in self._client_attributes:
573+
self._client_attributes[METRIC_LABEL_KEY_DATABASE] = database
574+
return self
575+
576+
def enable_direct_path(self, enable: bool = False) -> "MetricsTracer":
577+
"""
578+
Enable or disable the direct path for metrics tracing.
579+
580+
This method updates the direct path enabled attribute in the client attributes dictionary for metrics tracing purposes.
581+
If the direct path enabled attribute already has a value, this method does nothing and returns.
582+
583+
:param enable: Boolean indicating whether to enable the direct path.
584+
:return: This instance of MetricsTracer for method chaining.
585+
"""
586+
if METRIC_LABEL_KEY_DIRECT_PATH_ENABLED not in self._client_attributes:
587+
self._client_attributes[METRIC_LABEL_KEY_DIRECT_PATH_ENABLED] = str(enable)
588+
return self

0 commit comments

Comments
 (0)