Skip to content

Commit c770506

Browse files
committed
PYCBC-1718: Update metrics, orphan reporting and tracing config to align with C++ updates
Changes ======== * Update C++ core to pull in changes to metrics, orphan reporting and tracing * Add `ClusterMetricsOptions` and `ClusterOrphanReportingOptions` options blocks * Add deprecated notice to `ClusterTracingOptions` `tracing_orphaned_queue_size` and `tracing_orphaned_queue_flush_interval` options as those are now in `ClusterOrphanReportingOptions` * Add deprecated notice to `ClusterOptions` `logging_meter_emit_interval` as that option is now in `ClusterMetricsOptions` * Update cluster option processing logic to handle updated options blocks (and option values being able to come from multiple blocks) * Update connection tests to confirm new functionality * Update tracer tests to handle changes to C++ core Results ======= All tests pass. Change-Id: I65e65a3357498f8d0d0746599fcab3e8caf5d3cd Reviewed-on: https://review.couchbase.org/c/couchbase-python-client/+/235475 Reviewed-by: Dimitris Christodoulou <dimitris.christodoulou@couchbase.com> Tested-by: Build Bot <build@couchbase.com>
1 parent 9338788 commit c770506

File tree

7 files changed

+598
-119
lines changed

7 files changed

+598
-119
lines changed

couchbase/logic/cluster.py

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@
3030
from couchbase.auth import CertificateAuthenticator, PasswordAuthenticator
3131
from couchbase.diagnostics import ServiceType
3232
from couchbase.exceptions import InvalidArgumentException
33-
from couchbase.options import (ClusterOptions,
33+
from couchbase.options import (ClusterMetricsOptions,
34+
ClusterOptions,
35+
ClusterOrphanReportingOptions,
3436
ClusterTimeoutOptions,
3537
ClusterTracingOptions,
3638
TLSVerifyMode,
@@ -144,9 +146,48 @@ def __init__(self, # noqa: C901
144146
for key in ClusterTracingOptions.get_allowed_option_keys(use_transform_keys=True):
145147
if key in cluster_opts:
146148
tracing_opts[key] = cluster_opts.pop(key)
149+
150+
orphan_opts = {}
151+
for key in ClusterOrphanReportingOptions.get_allowed_option_keys(use_transform_keys=True):
152+
if key in cluster_opts:
153+
orphan_opts[key] = cluster_opts.pop(key)
154+
155+
# PYCBC-XXXX: C++ core split out orphan reporting from tracing, so we have separate options blocks now.
156+
# However, we have to check for the old options in the tracing block for backwards compatibility.
157+
if tracing_opts:
158+
sample_size = tracing_opts.pop('orphan_sample_size', None)
159+
if sample_size and 'sample_size' not in orphan_opts:
160+
orphan_opts['orphan_sample_size'] = sample_size
161+
emit_interval = tracing_opts.pop('orphan_emit_interval', None)
162+
if emit_interval and 'emit_interval' not in orphan_opts:
163+
orphan_opts['orphan_emit_interval'] = emit_interval
164+
165+
cluster_enable_tracing = cluster_opts.pop('cluster_enable_tracing', None)
166+
if cluster_enable_tracing is not None and 'enable_tracing' not in tracing_opts:
167+
tracing_opts['enable_tracing'] = cluster_enable_tracing
147168
if tracing_opts:
148169
cluster_opts['tracing_options'] = tracing_opts
149170

171+
cluster_enable_orphan_reporting = cluster_opts.pop('cluster_enable_orphan_reporting', None)
172+
if cluster_enable_orphan_reporting is not None and 'enable_orphan_reporting' not in orphan_opts:
173+
orphan_opts['enable_orphan_reporting'] = cluster_enable_orphan_reporting
174+
if orphan_opts:
175+
cluster_opts['orphan_reporting_options'] = orphan_opts
176+
177+
metrics_opts = {}
178+
for key in ClusterMetricsOptions.get_allowed_option_keys(use_transform_keys=True):
179+
if key in cluster_opts:
180+
metrics_opts[key] = cluster_opts.pop(key)
181+
182+
cluster_metrics_emit_interval = cluster_opts.pop('cluster_metrics_emit_interval', None)
183+
if cluster_metrics_emit_interval and 'metrics_emit_interval' not in metrics_opts:
184+
metrics_opts['metrics_emit_interval'] = cluster_metrics_emit_interval
185+
cluster_enable_metrics = cluster_opts.pop('cluster_enable_metrics', None)
186+
if cluster_enable_metrics is not None and 'enable_metrics' not in metrics_opts:
187+
metrics_opts['enable_metrics'] = cluster_enable_metrics
188+
if metrics_opts:
189+
cluster_opts['metrics_options'] = metrics_opts
190+
150191
self._default_serializer = cluster_opts.pop("serializer", None)
151192
if not self._default_serializer:
152193
self._default_serializer = DefaultJsonSerializer()

couchbase/logic/options.py

Lines changed: 125 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -454,9 +454,102 @@ def get_allowed_option_keys(use_transform_keys=False # type: Optional[bool]
454454
return list(ClusterTimeoutOptionsBase._VALID_OPTS.keys())
455455

456456

457+
class ClusterMetricsOptionsBase(dict):
458+
459+
_VALID_OPTS = {
460+
"metrics_enable_metrics": {"enable_metrics": validate_bool},
461+
"metrics_emit_interval": {"metrics_emit_interval": timedelta_as_microseconds}
462+
}
463+
464+
@overload
465+
def __init__(
466+
self,
467+
enable_metrics=None, # type: Optional[bool]
468+
emit_interval=None, # type: Optional[timedelta]
469+
):
470+
"""ClusterMetricsOptions instance."""
471+
472+
def __init__(self, **kwargs):
473+
kwargs = {f'metrics_{k}': v for k, v in kwargs.items() if v is not None}
474+
super().__init__(**kwargs)
475+
476+
def as_dict(self):
477+
opts = {}
478+
allowed_opts = ClusterMetricsOptionsBase.get_allowed_option_keys()
479+
for k, v in self.items():
480+
if k not in allowed_opts:
481+
continue
482+
if v is None:
483+
continue
484+
if isinstance(v, timedelta):
485+
opts[k] = v.total_seconds()
486+
elif isinstance(v, (int, float)):
487+
opts[k] = v
488+
return opts
489+
490+
@staticmethod
491+
def get_allowed_option_keys(use_transform_keys=False # type: Optional[bool]
492+
) -> List[str]:
493+
if use_transform_keys is True:
494+
keys = []
495+
for val in ClusterMetricsOptionsBase._VALID_OPTS.values():
496+
keys.append(list(val.keys())[0])
497+
return keys
498+
499+
return list(ClusterMetricsOptionsBase._VALID_OPTS.keys())
500+
501+
502+
class ClusterOrphanReportingOptionsBase(dict):
503+
504+
_VALID_OPTS = {
505+
"orphan_enable_orphan_reporting": {"enable_orphan_reporting": validate_bool},
506+
"orphan_sample_size": {"orphan_sample_size": validate_int},
507+
"orphan_emit_interval": {"orphan_emit_interval": timedelta_as_microseconds}
508+
}
509+
510+
@overload
511+
def __init__(
512+
self,
513+
enable_orphan_reporting=None, # type: Optional[bool]
514+
sample_size=None, # type: Optional[int]
515+
emit_interval=None, # type: Optional[timedelta]
516+
):
517+
"""ClusterOrphanReportingOptions instance."""
518+
519+
def __init__(self, **kwargs):
520+
kwargs = {f'orphan_{k}': v for k, v in kwargs.items() if v is not None}
521+
super().__init__(**kwargs)
522+
523+
def as_dict(self):
524+
opts = {}
525+
allowed_opts = ClusterOrphanReportingOptionsBase.get_allowed_option_keys()
526+
for k, v in self.items():
527+
if k not in allowed_opts:
528+
continue
529+
if v is None:
530+
continue
531+
if isinstance(v, timedelta):
532+
opts[k] = v.total_seconds()
533+
elif isinstance(v, (int, float)):
534+
opts[k] = v
535+
return opts
536+
537+
@staticmethod
538+
def get_allowed_option_keys(use_transform_keys=False # type: Optional[bool]
539+
) -> List[str]:
540+
if use_transform_keys is True:
541+
keys = []
542+
for val in ClusterOrphanReportingOptionsBase._VALID_OPTS.values():
543+
keys.append(list(val.keys())[0])
544+
return keys
545+
546+
return list(ClusterOrphanReportingOptionsBase._VALID_OPTS.keys())
547+
548+
457549
class ClusterTracingOptionsBase(dict):
458550

459551
_VALID_OPTS = {
552+
"tracing_enable_tracing": {"enable_tracing": validate_bool},
460553
"tracing_threshold_kv": {"key_value_threshold": timedelta_as_microseconds},
461554
"tracing_threshold_view": {"view_threshold": timedelta_as_microseconds},
462555
"tracing_threshold_query": {"query_threshold": timedelta_as_microseconds},
@@ -466,13 +559,14 @@ class ClusterTracingOptionsBase(dict):
466559
"tracing_threshold_management": {"management_threshold": timedelta_as_microseconds},
467560
"tracing_threshold_queue_size": {"threshold_sample_size": validate_int},
468561
"tracing_threshold_queue_flush_interval": {"threshold_emit_interval": timedelta_as_microseconds},
469-
"tracing_orphaned_queue_size": {"orphaned_sample_size": validate_int},
470-
"tracing_orphaned_queue_flush_interval": {"orphaned_emit_interval": timedelta_as_microseconds}
562+
"tracing_orphaned_queue_size": {"orphan_sample_size": validate_int},
563+
"tracing_orphaned_queue_flush_interval": {"orphan_emit_interval": timedelta_as_microseconds}
471564
}
472565

473566
@overload
474567
def __init__(
475568
self,
569+
enable_tracing=None, # type: Optional[bool]
476570
tracing_threshold_kv=None, # type: Optional[timedelta]
477571
tracing_threshold_view=None, # type: Optional[timedelta]
478572
tracing_threshold_query=None, # type: Optional[timedelta]
@@ -489,6 +583,9 @@ def __init__(
489583

490584
def __init__(self, **kwargs):
491585
kwargs = {k: v for k, v in kwargs.items() if v is not None}
586+
enable_tracing = kwargs.pop('enable_tracing', None)
587+
if enable_tracing is not None:
588+
kwargs['tracing_enable_tracing'] = enable_tracing
492589
super().__init__(**kwargs)
493590

494591
def as_dict(self):
@@ -535,8 +632,9 @@ class ClusterOptionsBase(dict):
535632
"enable_unordered_execution": {"enable_unordered_execution": validate_bool},
536633
"enable_clustermap_notification": {"enable_clustermap_notification": validate_bool},
537634
"enable_compression": {"enable_compression": validate_bool},
538-
"enable_tracing": {"enable_tracing": validate_bool},
539-
"enable_metrics": {"enable_metrics": validate_bool},
635+
"enable_tracing": {"cluster_enable_tracing": validate_bool},
636+
"enable_metrics": {"cluster_enable_metrics": validate_bool},
637+
"enable_orphan_reporting": {"cluster_enable_orphan_reporting": validate_bool},
540638
"network": {"network": validate_str},
541639
"tls_verify": {"tls_verify": TLSVerifyMode.to_str},
542640
"serializer": {"serializer": lambda x: x},
@@ -550,7 +648,7 @@ class ClusterOptionsBase(dict):
550648
"trust_store_path": {"trust_store_path": validate_str},
551649
"cert_path": {"cert_path": validate_str},
552650
"disable_mozilla_ca_certificates": {"disable_mozilla_ca_certificates": validate_bool},
553-
"logging_meter_emit_interval": {"emit_interval": timedelta_as_microseconds},
651+
"logging_meter_emit_interval": {"cluster_metrics_emit_interval": timedelta_as_microseconds},
554652
"num_io_threads": {"num_io_threads": validate_int},
555653
"transaction_config": {"transaction_config": lambda x: x},
556654
"tracer": {"tracer": lambda x: x},
@@ -572,6 +670,8 @@ def __init__(
572670
self,
573671
authenticator, # type: Authenticator
574672
timeout_options=None, # type: Optional[ClusterTimeoutOptionsBase]
673+
orphan_reporting_options=None, # type: Optional[ClusterOrphanReportingOptionsBase]
674+
metrics_options=None, # type: Optional[ClusterMetricsOptionsBase]
575675
tracing_options=None, # type: Optional[ClusterTracingOptionsBase]
576676
enable_tls=None, # type: Optional[bool]
577677
enable_mutation_tokens=None, # type: Optional[bool]
@@ -584,6 +684,7 @@ def __init__(
584684
enable_compression=None, # type: Optional[bool]
585685
enable_tracing=None, # type: Optional[bool]
586686
enable_metrics=None, # type: Optional[bool]
687+
enable_orphan_reporting=None, # type: Optional[bool]
587688
network=None, # type: Optional[str]
588689
tls_verify=None, # type: Optional[Union[TLSVerifyMode, str]]
589690
serializer=None, # type: Optional[Serializer]
@@ -616,7 +717,7 @@ def __init__(
616717
):
617718
"""ClusterOptions instance."""
618719

619-
def __init__(self,
720+
def __init__(self, # noqa: C901
620721
authenticator, # type: Authenticator
621722
**kwargs
622723
):
@@ -631,6 +732,18 @@ def __init__(self,
631732
if k not in kwargs:
632733
kwargs[k] = v
633734

735+
orphan_opts = kwargs.pop('orphan_reporting_options', {})
736+
if orphan_opts:
737+
for k, v in orphan_opts.items():
738+
if k not in kwargs:
739+
kwargs[k] = v
740+
741+
metrics_opts = kwargs.pop('metrics_options', {})
742+
if metrics_opts:
743+
for k, v in metrics_opts.items():
744+
if k not in kwargs:
745+
kwargs[k] = v
746+
634747
timeout_opts = kwargs.pop('timeout_options', {})
635748
if timeout_opts:
636749
for k, v in timeout_opts.items():
@@ -654,13 +767,17 @@ def get_allowed_option_keys(cluster_opts_only=False, # type: Optional[bool]
654767

655768
keys.extend(ClusterTimeoutOptionsBase.get_allowed_option_keys(use_transform_keys=True))
656769
keys.extend(ClusterTracingOptionsBase.get_allowed_option_keys(use_transform_keys=True))
770+
keys.extend(ClusterMetricsOptionsBase.get_allowed_option_keys(use_transform_keys=True))
771+
keys.extend(ClusterOrphanReportingOptionsBase.get_allowed_option_keys(use_transform_keys=True))
657772

658773
return keys
659774

660775
if cluster_opts_only is True:
661776
return list(ClusterOptionsBase._VALID_OPTS.keys())
662777

663778
valid_keys = ClusterTimeoutOptionsBase.get_allowed_option_keys()
779+
valid_keys.extend(ClusterOrphanReportingOptionsBase.get_allowed_option_keys())
780+
valid_keys.extend(ClusterMetricsOptionsBase.get_allowed_option_keys())
664781
valid_keys.extend(ClusterTracingOptionsBase.get_allowed_option_keys())
665782
valid_keys.extend(list(ClusterOptionsBase._VALID_OPTS.keys()))
666783

@@ -669,6 +786,8 @@ def get_allowed_option_keys(cluster_opts_only=False, # type: Optional[bool]
669786
@staticmethod
670787
def get_valid_options() -> Dict[str, Any]:
671788
valid_opts = copy.copy(ClusterTimeoutOptionsBase._VALID_OPTS)
789+
valid_opts.update(copy.copy(ClusterMetricsOptionsBase._VALID_OPTS))
790+
valid_opts.update(copy.copy(ClusterOrphanReportingOptionsBase._VALID_OPTS))
672791
valid_opts.update(copy.copy(ClusterTracingOptionsBase._VALID_OPTS))
673792
valid_opts.update(copy.copy(ClusterOptionsBase._VALID_OPTS))
674793
return valid_opts

0 commit comments

Comments
 (0)