2023-05-14 10:43:59 +00:00
|
|
|
from abc import ABC
|
2023-12-20 13:02:54 +00:00
|
|
|
from typing import Any, Optional
|
2023-05-14 10:43:59 +00:00
|
|
|
|
|
|
|
from frostfs_testlib.load.load_config import LoadScenario
|
|
|
|
|
|
|
|
|
2023-12-20 13:02:54 +00:00
|
|
|
class OperationMetric(ABC):
|
|
|
|
_NAME = ""
|
|
|
|
_SUCCESS = ""
|
|
|
|
_ERRORS = ""
|
|
|
|
_THROUGHPUT = ""
|
|
|
|
_LATENCY = ""
|
2023-05-14 10:43:59 +00:00
|
|
|
|
|
|
|
def __init__(self, summary) -> None:
|
|
|
|
self.summary = summary
|
|
|
|
self.metrics = summary["metrics"]
|
|
|
|
|
|
|
|
@property
|
2023-12-20 13:02:54 +00:00
|
|
|
def total_iterations(self) -> int:
|
|
|
|
return self._get_metric(self._SUCCESS) + self._get_metric(self._ERRORS)
|
2023-10-03 12:18:29 +00:00
|
|
|
|
2023-09-06 17:47:30 +00:00
|
|
|
@property
|
2023-12-20 13:02:54 +00:00
|
|
|
def success_iterations(self) -> int:
|
|
|
|
return self._get_metric(self._SUCCESS)
|
2023-05-14 10:43:59 +00:00
|
|
|
|
|
|
|
@property
|
2023-12-20 13:02:54 +00:00
|
|
|
def latency(self) -> dict:
|
|
|
|
return self._get_metric(self._LATENCY)
|
2023-05-14 10:43:59 +00:00
|
|
|
|
|
|
|
@property
|
2023-12-20 13:02:54 +00:00
|
|
|
def rate(self) -> float:
|
|
|
|
return self._get_metric_rate(self._SUCCESS)
|
2023-05-14 10:43:59 +00:00
|
|
|
|
|
|
|
@property
|
2023-12-20 13:02:54 +00:00
|
|
|
def failed_iterations(self) -> int:
|
|
|
|
return self._get_metric(self._ERRORS)
|
2023-05-14 10:43:59 +00:00
|
|
|
|
|
|
|
@property
|
2023-12-20 13:02:54 +00:00
|
|
|
def throughput(self) -> float:
|
|
|
|
return self._get_metric_rate(self._THROUGHPUT)
|
2023-05-14 10:43:59 +00:00
|
|
|
|
|
|
|
def _get_metric(self, metric: str) -> int:
|
2023-10-03 12:18:29 +00:00
|
|
|
metrics_method_map = {
|
|
|
|
"counter": self._get_counter_metric,
|
|
|
|
"gauge": self._get_gauge_metric,
|
|
|
|
"trend": self._get_trend_metrics,
|
|
|
|
}
|
2023-05-14 10:43:59 +00:00
|
|
|
|
|
|
|
if metric not in self.metrics:
|
|
|
|
return 0
|
|
|
|
|
|
|
|
metric = self.metrics[metric]
|
|
|
|
metric_type = metric["type"]
|
|
|
|
if metric_type not in metrics_method_map:
|
2023-12-20 13:02:54 +00:00
|
|
|
raise Exception(f"Unsupported metric type: {metric_type}, supported: {metrics_method_map.keys()}")
|
2023-05-14 10:43:59 +00:00
|
|
|
|
|
|
|
return metrics_method_map[metric_type](metric)
|
|
|
|
|
|
|
|
def _get_metric_rate(self, metric: str) -> int:
|
|
|
|
metrics_method_map = {"counter": self._get_counter_metric_rate}
|
|
|
|
|
|
|
|
if metric not in self.metrics:
|
|
|
|
return 0
|
|
|
|
|
|
|
|
metric = self.metrics[metric]
|
|
|
|
metric_type = metric["type"]
|
|
|
|
if metric_type not in metrics_method_map:
|
2023-12-20 13:02:54 +00:00
|
|
|
raise Exception(f"Unsupported rate metric type: {metric_type}, supported: {metrics_method_map.keys()}")
|
2023-05-14 10:43:59 +00:00
|
|
|
|
|
|
|
return metrics_method_map[metric_type](metric)
|
|
|
|
|
|
|
|
def _get_counter_metric_rate(self, metric: str) -> int:
|
|
|
|
return metric["values"]["rate"]
|
|
|
|
|
|
|
|
def _get_counter_metric(self, metric: str) -> int:
|
|
|
|
return metric["values"]["count"]
|
|
|
|
|
|
|
|
def _get_gauge_metric(self, metric: str) -> int:
|
|
|
|
return metric["values"]["value"]
|
2023-10-03 12:18:29 +00:00
|
|
|
|
|
|
|
def _get_trend_metrics(self, metric: str) -> int:
|
2023-09-06 17:47:30 +00:00
|
|
|
return metric["values"]
|
2023-05-14 10:43:59 +00:00
|
|
|
|
|
|
|
|
2023-12-20 13:02:54 +00:00
|
|
|
class WriteOperationMetric(OperationMetric):
|
|
|
|
_NAME = "Write"
|
|
|
|
_SUCCESS = ""
|
|
|
|
_ERRORS = ""
|
|
|
|
_THROUGHPUT = "data_sent"
|
|
|
|
_LATENCY = ""
|
2023-05-14 10:43:59 +00:00
|
|
|
|
|
|
|
|
2023-12-20 13:02:54 +00:00
|
|
|
class ReadOperationMetric(OperationMetric):
|
|
|
|
_NAME = "Read"
|
|
|
|
_SUCCESS = ""
|
|
|
|
_ERRORS = ""
|
|
|
|
_THROUGHPUT = "data_received"
|
|
|
|
_LATENCY = ""
|
2023-05-14 10:43:59 +00:00
|
|
|
|
|
|
|
|
2023-12-20 13:02:54 +00:00
|
|
|
class DeleteOperationMetric(OperationMetric):
|
|
|
|
_NAME = "Delete"
|
|
|
|
_SUCCESS = ""
|
|
|
|
_ERRORS = ""
|
|
|
|
_THROUGHPUT = ""
|
|
|
|
_LATENCY = ""
|
2023-05-14 10:43:59 +00:00
|
|
|
|
|
|
|
|
2023-12-20 13:02:54 +00:00
|
|
|
class GrpcWriteOperationMetric(WriteOperationMetric):
|
|
|
|
_SUCCESS = "frostfs_obj_put_total"
|
|
|
|
_ERRORS = "frostfs_obj_put_fails"
|
|
|
|
_LATENCY = "frostfs_obj_put_duration"
|
2023-05-14 10:43:59 +00:00
|
|
|
|
2023-11-14 11:00:08 +00:00
|
|
|
|
2023-12-20 13:02:54 +00:00
|
|
|
class GrpcReadOperationMetric(ReadOperationMetric):
|
|
|
|
_SUCCESS = "frostfs_obj_get_total"
|
|
|
|
_ERRORS = "frostfs_obj_get_fails"
|
|
|
|
_LATENCY = "frostfs_obj_get_duration"
|
2023-05-14 10:43:59 +00:00
|
|
|
|
2023-06-26 13:45:34 +00:00
|
|
|
|
2023-12-20 13:02:54 +00:00
|
|
|
class GrpcDeleteOperationMetric(DeleteOperationMetric):
|
|
|
|
_SUCCESS = "frostfs_obj_delete_total"
|
|
|
|
_ERRORS = "frostfs_obj_delete_fails"
|
|
|
|
_LATENCY = "frostfs_obj_delete_duration"
|
2023-06-26 13:45:34 +00:00
|
|
|
|
|
|
|
|
2023-12-20 13:02:54 +00:00
|
|
|
class S3WriteOperationMetric(WriteOperationMetric):
|
|
|
|
_SUCCESS = "aws_obj_put_total"
|
|
|
|
_ERRORS = "aws_obj_put_fails"
|
|
|
|
_LATENCY = "aws_obj_put_duration"
|
|
|
|
|
|
|
|
|
|
|
|
class S3ReadOperationMetric(ReadOperationMetric):
|
|
|
|
_SUCCESS = "aws_obj_get_total"
|
|
|
|
_ERRORS = "aws_obj_get_fails"
|
|
|
|
_LATENCY = "aws_obj_get_duration"
|
|
|
|
|
|
|
|
|
|
|
|
class S3DeleteOperationMetric(DeleteOperationMetric):
|
|
|
|
_SUCCESS = "aws_obj_delete_total"
|
|
|
|
_ERRORS = "aws_obj_delete_fails"
|
|
|
|
_LATENCY = "aws_obj_delete_duration"
|
2023-06-26 13:45:34 +00:00
|
|
|
|
2023-05-14 10:43:59 +00:00
|
|
|
|
2023-12-20 13:02:54 +00:00
|
|
|
class S3LocalWriteOperationMetric(WriteOperationMetric):
|
|
|
|
_SUCCESS = "s3local_obj_put_total"
|
|
|
|
_ERRORS = "s3local_obj_put_fails"
|
|
|
|
_LATENCY = "s3local_obj_put_duration"
|
2023-05-14 10:43:59 +00:00
|
|
|
|
2023-12-20 13:02:54 +00:00
|
|
|
|
|
|
|
class S3LocalReadOperationMetric(ReadOperationMetric):
|
|
|
|
_SUCCESS = "s3local_obj_get_total"
|
|
|
|
_ERRORS = "s3local_obj_get_fails"
|
|
|
|
_LATENCY = "s3local_obj_get_duration"
|
|
|
|
|
|
|
|
|
|
|
|
class LocalWriteOperationMetric(WriteOperationMetric):
|
|
|
|
_SUCCESS = "local_obj_put_total"
|
|
|
|
_ERRORS = "local_obj_put_fails"
|
|
|
|
_LATENCY = "local_obj_put_duration"
|
|
|
|
|
|
|
|
|
|
|
|
class LocalReadOperationMetric(ReadOperationMetric):
|
|
|
|
_SUCCESS = "local_obj_get_total"
|
|
|
|
_ERRORS = "local_obj_get_fails"
|
|
|
|
|
|
|
|
|
|
|
|
class LocalDeleteOperationMetric(DeleteOperationMetric):
|
|
|
|
_SUCCESS = "local_obj_delete_total"
|
|
|
|
_ERRORS = "local_obj_delete_fails"
|
|
|
|
|
|
|
|
|
|
|
|
class VerifyReadOperationMetric(ReadOperationMetric):
|
|
|
|
_SUCCESS = "verified_obj"
|
|
|
|
_ERRORS = "invalid_obj"
|
|
|
|
|
|
|
|
|
|
|
|
class MetricsBase(ABC):
|
|
|
|
def __init__(self) -> None:
|
|
|
|
self.write: Optional[WriteOperationMetric] = None
|
|
|
|
self.read: Optional[ReadOperationMetric] = None
|
|
|
|
self.delete: Optional[DeleteOperationMetric] = None
|
|
|
|
|
|
|
|
@property
|
|
|
|
def operations(self) -> list[OperationMetric]:
|
|
|
|
return [metric for metric in [self.write, self.read, self.delete] if metric is not None]
|
|
|
|
|
|
|
|
|
|
|
|
class GrpcMetrics(MetricsBase):
|
|
|
|
def __init__(self, summary) -> None:
|
|
|
|
super().__init__()
|
|
|
|
self.write = GrpcWriteOperationMetric(summary)
|
|
|
|
self.read = GrpcReadOperationMetric(summary)
|
|
|
|
self.delete = GrpcDeleteOperationMetric(summary)
|
|
|
|
|
|
|
|
|
|
|
|
class S3Metrics(MetricsBase):
|
|
|
|
def __init__(self, summary) -> None:
|
|
|
|
super().__init__()
|
|
|
|
self.write = S3WriteOperationMetric(summary)
|
|
|
|
self.read = S3ReadOperationMetric(summary)
|
|
|
|
self.delete = S3DeleteOperationMetric(summary)
|
|
|
|
|
|
|
|
|
|
|
|
class S3LocalMetrics(MetricsBase):
|
|
|
|
def __init__(self, summary) -> None:
|
|
|
|
super().__init__()
|
|
|
|
self.write = S3LocalWriteOperationMetric(summary)
|
|
|
|
self.read = S3LocalReadOperationMetric(summary)
|
|
|
|
|
|
|
|
|
|
|
|
class LocalMetrics(MetricsBase):
|
|
|
|
def __init__(self, summary) -> None:
|
|
|
|
super().__init__()
|
|
|
|
self.write = LocalWriteOperationMetric(summary)
|
|
|
|
self.read = LocalReadOperationMetric(summary)
|
|
|
|
self.delete = LocalDeleteOperationMetric(summary)
|
|
|
|
|
|
|
|
|
|
|
|
class VerifyMetrics(MetricsBase):
|
|
|
|
def __init__(self, summary) -> None:
|
|
|
|
super().__init__()
|
|
|
|
self.read = VerifyReadOperationMetric(summary)
|
2023-05-14 10:43:59 +00:00
|
|
|
|
|
|
|
|
|
|
|
def get_metrics_object(load_type: LoadScenario, summary: dict[str, Any]) -> MetricsBase:
|
|
|
|
class_map = {
|
|
|
|
LoadScenario.gRPC: GrpcMetrics,
|
|
|
|
LoadScenario.gRPC_CAR: GrpcMetrics,
|
|
|
|
LoadScenario.HTTP: GrpcMetrics,
|
|
|
|
LoadScenario.S3: S3Metrics,
|
|
|
|
LoadScenario.S3_CAR: S3Metrics,
|
2023-10-27 07:56:27 +00:00
|
|
|
LoadScenario.S3_MULTIPART: S3Metrics,
|
2023-11-14 11:00:08 +00:00
|
|
|
LoadScenario.S3_LOCAL: S3LocalMetrics,
|
2023-05-14 10:43:59 +00:00
|
|
|
LoadScenario.VERIFY: VerifyMetrics,
|
2023-06-26 13:45:34 +00:00
|
|
|
LoadScenario.LOCAL: LocalMetrics,
|
2023-05-14 10:43:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return class_map[load_type](summary)
|