test-api: add a check for each stat parsing
Signed-off-by: Kamil Gierszewski <kamil.gierszewski@huawei.com>
This commit is contained in:
parent
7b52a2fc00
commit
bf7c72ccba
@ -11,6 +11,7 @@ from enum import Enum
|
|||||||
from typing import List
|
from typing import List
|
||||||
from api.cas import casadm
|
from api.cas import casadm
|
||||||
from api.cas.casadm_params import StatsFilter
|
from api.cas.casadm_params import StatsFilter
|
||||||
|
from connection.utils.output import CmdException
|
||||||
from type_def.size import Size, Unit
|
from type_def.size import Size, Unit
|
||||||
|
|
||||||
|
|
||||||
@ -58,6 +59,9 @@ class CacheStats:
|
|||||||
case StatsFilter.err:
|
case StatsFilter.err:
|
||||||
self.error_stats = ErrorStats(stats_dict, percentage_val)
|
self.error_stats = ErrorStats(stats_dict, percentage_val)
|
||||||
|
|
||||||
|
if stats_dict:
|
||||||
|
raise CmdException(f"Unknown stat(s) left after parsing output cmd\n{stats_dict}")
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
# stats_list contains all Class.__str__ methods initialized in CacheStats
|
# stats_list contains all Class.__str__ methods initialized in CacheStats
|
||||||
stats_list = [str(getattr(self, stats_item)) for stats_item in self.__dict__]
|
stats_list = [str(getattr(self, stats_item)) for stats_item in self.__dict__]
|
||||||
@ -72,13 +76,6 @@ class CacheStats:
|
|||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
return iter([getattr(self, stats_item) for stats_item in self.__dict__])
|
return iter([getattr(self, stats_item) for stats_item in self.__dict__])
|
||||||
|
|
||||||
def __sub__(self, other):
|
|
||||||
self.usage_stats -= other.usage_stats
|
|
||||||
self.request_stats -= other.request_stats
|
|
||||||
self.block_stats -= other.block_stats
|
|
||||||
self.error_stats -= other.error_stats
|
|
||||||
return self
|
|
||||||
|
|
||||||
|
|
||||||
class CoreStats:
|
class CoreStats:
|
||||||
def __init__(
|
def __init__(
|
||||||
@ -103,12 +100,8 @@ class CoreStats:
|
|||||||
case StatsFilter.err:
|
case StatsFilter.err:
|
||||||
self.error_stats = ErrorStats(stats_dict, percentage_val)
|
self.error_stats = ErrorStats(stats_dict, percentage_val)
|
||||||
|
|
||||||
def __sub__(self, other):
|
if stats_dict:
|
||||||
self.usage_stats -= other.usage_stats
|
raise CmdException(f"Unknown stat(s) left after parsing output cmd\n{stats_dict}")
|
||||||
self.request_stats -= other.request_stats
|
|
||||||
self.block_stats -= other.block_stats
|
|
||||||
self.error_stats -= other.error_stats
|
|
||||||
return self
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
# stats_list contains all Class.__str__ methods initialized in CacheStats
|
# stats_list contains all Class.__str__ methods initialized in CacheStats
|
||||||
@ -149,6 +142,9 @@ class CoreIoClassStats:
|
|||||||
case StatsFilter.blk:
|
case StatsFilter.blk:
|
||||||
self.block_stats = BlockStats(stats_dict, percentage_val)
|
self.block_stats = BlockStats(stats_dict, percentage_val)
|
||||||
|
|
||||||
|
if stats_dict:
|
||||||
|
raise CmdException(f"Unknown stat(s) left after parsing output cmd\n{stats_dict}")
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
# check if all initialized variable in self(CacheStats) match other(CacheStats)
|
# check if all initialized variable in self(CacheStats) match other(CacheStats)
|
||||||
return [getattr(self, stats_item) for stats_item in self.__dict__] == [
|
return [getattr(self, stats_item) for stats_item in self.__dict__] == [
|
||||||
@ -163,11 +159,6 @@ class CoreIoClassStats:
|
|||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
return iter([getattr(self, stats_item) for stats_item in self.__dict__])
|
return iter([getattr(self, stats_item) for stats_item in self.__dict__])
|
||||||
|
|
||||||
def __sub__(self, other):
|
|
||||||
self.usage_stats -= other.usage_stats
|
|
||||||
self.request_stats -= other.request_stats
|
|
||||||
self.block_stats -= other.block_stats
|
|
||||||
|
|
||||||
|
|
||||||
class CacheIoClassStats(CoreIoClassStats):
|
class CacheIoClassStats(CoreIoClassStats):
|
||||||
def __init__(
|
def __init__(
|
||||||
@ -211,6 +202,22 @@ class CacheConfigStats:
|
|||||||
self.dirty_for = parse_value(value=stats_dict["Dirty for [s]"], unit_type=UnitType.seconds)
|
self.dirty_for = parse_value(value=stats_dict["Dirty for [s]"], unit_type=UnitType.seconds)
|
||||||
self.status = stats_dict["Status"]
|
self.status = stats_dict["Status"]
|
||||||
|
|
||||||
|
del stats_dict["Cache Id"]
|
||||||
|
del stats_dict["Cache Size [4KiB Blocks]"]
|
||||||
|
del stats_dict["Cache Size [GiB]"]
|
||||||
|
del stats_dict["Cache Device"]
|
||||||
|
del stats_dict["Exported Object"]
|
||||||
|
del stats_dict["Core Devices"]
|
||||||
|
del stats_dict["Inactive Core Devices"]
|
||||||
|
del stats_dict["Write Policy"]
|
||||||
|
del stats_dict["Cleaning Policy"]
|
||||||
|
del stats_dict["Promotion Policy"]
|
||||||
|
del stats_dict["Cache line size [KiB]"]
|
||||||
|
del stats_dict[footprint_key]
|
||||||
|
del stats_dict["Dirty for [s]"]
|
||||||
|
del stats_dict["Dirty for"]
|
||||||
|
del stats_dict["Status"]
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return (
|
return (
|
||||||
f"Config stats:\n"
|
f"Config stats:\n"
|
||||||
@ -254,7 +261,7 @@ class CacheConfigStats:
|
|||||||
|
|
||||||
class CoreConfigStats:
|
class CoreConfigStats:
|
||||||
def __init__(self, stats_dict):
|
def __init__(self, stats_dict):
|
||||||
self.core_id = stats_dict["Core Id"]
|
self.core_id = int(stats_dict["Core Id"])
|
||||||
self.core_dev = stats_dict["Core Device"]
|
self.core_dev = stats_dict["Core Device"]
|
||||||
self.exp_obj = stats_dict["Exported Object"]
|
self.exp_obj = stats_dict["Exported Object"]
|
||||||
self.core_size = parse_value(
|
self.core_size = parse_value(
|
||||||
@ -267,6 +274,17 @@ class CoreConfigStats:
|
|||||||
)
|
)
|
||||||
self.seq_cutoff_policy = stats_dict["Seq cutoff policy"]
|
self.seq_cutoff_policy = stats_dict["Seq cutoff policy"]
|
||||||
|
|
||||||
|
del stats_dict["Core Id"]
|
||||||
|
del stats_dict["Core Device"]
|
||||||
|
del stats_dict["Exported Object"]
|
||||||
|
del stats_dict["Core Size [4KiB Blocks]"]
|
||||||
|
del stats_dict["Core Size [GiB]"]
|
||||||
|
del stats_dict["Dirty for [s]"]
|
||||||
|
del stats_dict["Dirty for"]
|
||||||
|
del stats_dict["Status"]
|
||||||
|
del stats_dict["Seq cutoff threshold [KiB]"]
|
||||||
|
del stats_dict["Seq cutoff policy"]
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return (
|
return (
|
||||||
f"Config stats:\n"
|
f"Config stats:\n"
|
||||||
@ -305,6 +323,11 @@ class IoClassConfigStats:
|
|||||||
self.eviction_priority = stats_dict["Eviction priority"]
|
self.eviction_priority = stats_dict["Eviction priority"]
|
||||||
self.max_size = stats_dict["Max size"]
|
self.max_size = stats_dict["Max size"]
|
||||||
|
|
||||||
|
del stats_dict["IO class ID"]
|
||||||
|
del stats_dict["IO class name"]
|
||||||
|
del stats_dict["Eviction priority"]
|
||||||
|
del stats_dict["Max size"]
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return (
|
return (
|
||||||
f"Config stats:\n"
|
f"Config stats:\n"
|
||||||
@ -348,6 +371,18 @@ class UsageStats:
|
|||||||
value=stats_dict[f"Inactive Dirty {unit}"], unit_type=unit
|
value=stats_dict[f"Inactive Dirty {unit}"], unit_type=unit
|
||||||
)
|
)
|
||||||
|
|
||||||
|
for unit in [UnitType.percentage, UnitType.block_4k]:
|
||||||
|
del stats_dict[f"Occupancy {unit}"]
|
||||||
|
del stats_dict[f"Free {unit}"]
|
||||||
|
del stats_dict[f"Clean {unit}"]
|
||||||
|
del stats_dict[f"Dirty {unit}"]
|
||||||
|
if f"Inactive Dirty {unit}" in stats_dict:
|
||||||
|
del stats_dict[f"Inactive Occupancy {unit}"]
|
||||||
|
if f"Inactive Clean {unit}" in stats_dict:
|
||||||
|
del stats_dict[f"Inactive Clean {unit}"]
|
||||||
|
if f"Inactive Dirty {unit}" in stats_dict:
|
||||||
|
del stats_dict[f"Inactive Dirty {unit}"]
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return (
|
return (
|
||||||
f"Usage stats:\n"
|
f"Usage stats:\n"
|
||||||
@ -376,13 +411,6 @@ class UsageStats:
|
|||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
return iter([getattr(self, stats_item) for stats_item in self.__dict__])
|
return iter([getattr(self, stats_item) for stats_item in self.__dict__])
|
||||||
|
|
||||||
def __sub__(self, other):
|
|
||||||
self.occupancy -= other.occupancy
|
|
||||||
self.free -= other.free
|
|
||||||
self.clean -= other.clean
|
|
||||||
self.dirty -= other.dirty
|
|
||||||
return self
|
|
||||||
|
|
||||||
|
|
||||||
class IoClassUsageStats:
|
class IoClassUsageStats:
|
||||||
def __init__(self, stats_dict, percentage_val):
|
def __init__(self, stats_dict, percentage_val):
|
||||||
@ -391,6 +419,11 @@ class IoClassUsageStats:
|
|||||||
self.clean = parse_value(value=stats_dict[f"Clean {unit}"], unit_type=unit)
|
self.clean = parse_value(value=stats_dict[f"Clean {unit}"], unit_type=unit)
|
||||||
self.dirty = parse_value(value=stats_dict[f"Dirty {unit}"], unit_type=unit)
|
self.dirty = parse_value(value=stats_dict[f"Dirty {unit}"], unit_type=unit)
|
||||||
|
|
||||||
|
for unit in [UnitType.percentage, UnitType.block_4k]:
|
||||||
|
del stats_dict[f"Occupancy {unit}"]
|
||||||
|
del stats_dict[f"Clean {unit}"]
|
||||||
|
del stats_dict[f"Dirty {unit}"]
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return (
|
return (
|
||||||
f"Usage stats:\n"
|
f"Usage stats:\n"
|
||||||
@ -417,21 +450,19 @@ class IoClassUsageStats:
|
|||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
return iter([getattr(self, stats_item) for stats_item in self.__dict__])
|
return iter([getattr(self, stats_item) for stats_item in self.__dict__])
|
||||||
|
|
||||||
def __sub__(self, other):
|
|
||||||
self.occupancy -= other.occupancy
|
|
||||||
self.clean -= other.clean
|
|
||||||
self.dirty -= other.dirty
|
|
||||||
return self
|
|
||||||
|
|
||||||
|
|
||||||
class RequestStats:
|
class RequestStats:
|
||||||
def __init__(self, stats_dict, percentage_val):
|
def __init__(self, stats_dict, percentage_val):
|
||||||
unit = UnitType.percentage if percentage_val else UnitType.requests
|
unit = UnitType.percentage if percentage_val else UnitType.requests
|
||||||
self.read = RequestStatsChunk(
|
self.read = RequestStatsChunk(
|
||||||
stats_dict=stats_dict, percentage_val=percentage_val, operation=OperationType.read
|
stats_dict=stats_dict,
|
||||||
|
percentage_val=percentage_val,
|
||||||
|
operation=OperationType.read,
|
||||||
)
|
)
|
||||||
self.write = RequestStatsChunk(
|
self.write = RequestStatsChunk(
|
||||||
stats_dict=stats_dict, percentage_val=percentage_val, operation=OperationType.write
|
stats_dict=stats_dict,
|
||||||
|
percentage_val=percentage_val,
|
||||||
|
operation=OperationType.write,
|
||||||
)
|
)
|
||||||
self.pass_through_reads = parse_value(
|
self.pass_through_reads = parse_value(
|
||||||
value=stats_dict[f"Pass-Through reads {unit}"], unit_type=unit
|
value=stats_dict[f"Pass-Through reads {unit}"], unit_type=unit
|
||||||
@ -446,6 +477,17 @@ class RequestStats:
|
|||||||
value=stats_dict[f"Total requests {unit}"], unit_type=unit
|
value=stats_dict[f"Total requests {unit}"], unit_type=unit
|
||||||
)
|
)
|
||||||
|
|
||||||
|
for unit in [UnitType.percentage, UnitType.requests]:
|
||||||
|
for operation in [OperationType.read, OperationType.write]:
|
||||||
|
del stats_dict[f"{operation} hits {unit}"]
|
||||||
|
del stats_dict[f"{operation} partial misses {unit}"]
|
||||||
|
del stats_dict[f"{operation} full misses {unit}"]
|
||||||
|
del stats_dict[f"{operation} total {unit}"]
|
||||||
|
del stats_dict[f"Pass-Through reads {unit}"]
|
||||||
|
del stats_dict[f"Pass-Through writes {unit}"]
|
||||||
|
del stats_dict[f"Serviced requests {unit}"]
|
||||||
|
del stats_dict[f"Total requests {unit}"]
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return (
|
return (
|
||||||
f"Request stats:\n"
|
f"Request stats:\n"
|
||||||
@ -472,15 +514,6 @@ class RequestStats:
|
|||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
return iter([getattr(self, stats_item) for stats_item in self.__dict__])
|
return iter([getattr(self, stats_item) for stats_item in self.__dict__])
|
||||||
|
|
||||||
def __sub__(self, other):
|
|
||||||
self.read -= other.read
|
|
||||||
self.write -= other.write
|
|
||||||
self.pass_through_reads -= other.pass_through_reads
|
|
||||||
self.pass_through_writes -= other.pass_through_writes
|
|
||||||
self.requests_serviced -= other.requests_serviced
|
|
||||||
self.requests_total -= other.requests_total
|
|
||||||
return self
|
|
||||||
|
|
||||||
|
|
||||||
class RequestStatsChunk:
|
class RequestStatsChunk:
|
||||||
def __init__(self, stats_dict, percentage_val: bool, operation: OperationType):
|
def __init__(self, stats_dict, percentage_val: bool, operation: OperationType):
|
||||||
@ -515,13 +548,6 @@ class RequestStatsChunk:
|
|||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
return iter([getattr(self, stats_item) for stats_item in self.__dict__])
|
return iter([getattr(self, stats_item) for stats_item in self.__dict__])
|
||||||
|
|
||||||
def __sub__(self, other):
|
|
||||||
self.hits -= other.hits
|
|
||||||
self.part_misses -= other.part_misses
|
|
||||||
self.full_misses -= other.full_misses
|
|
||||||
self.total -= other.total
|
|
||||||
return self
|
|
||||||
|
|
||||||
|
|
||||||
class BlockStats:
|
class BlockStats:
|
||||||
def __init__(self, stats_dict, percentage_val):
|
def __init__(self, stats_dict, percentage_val):
|
||||||
@ -537,6 +563,12 @@ class BlockStats:
|
|||||||
device="exported object",
|
device="exported object",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
for unit in [UnitType.percentage, UnitType.block_4k]:
|
||||||
|
for device in ["core", "cache", "exported object"]:
|
||||||
|
del stats_dict[f"Reads from {device} {unit}"]
|
||||||
|
del stats_dict[f"Writes to {device} {unit}"]
|
||||||
|
del stats_dict[f"Total to/from {device} {unit}"]
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return (
|
return (
|
||||||
f"Block stats:\n"
|
f"Block stats:\n"
|
||||||
@ -555,12 +587,6 @@ class BlockStats:
|
|||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
return iter([getattr(self, stats_item) for stats_item in self.__dict__])
|
return iter([getattr(self, stats_item) for stats_item in self.__dict__])
|
||||||
|
|
||||||
def __sub__(self, other):
|
|
||||||
self.core -= other.core
|
|
||||||
self.cache -= other.cache
|
|
||||||
self.exp_obj -= other.exp_obj
|
|
||||||
return self
|
|
||||||
|
|
||||||
|
|
||||||
class ErrorStats:
|
class ErrorStats:
|
||||||
def __init__(self, stats_dict, percentage_val):
|
def __init__(self, stats_dict, percentage_val):
|
||||||
@ -573,6 +599,13 @@ class ErrorStats:
|
|||||||
)
|
)
|
||||||
self.total_errors = parse_value(value=stats_dict[f"Total errors {unit}"], unit_type=unit)
|
self.total_errors = parse_value(value=stats_dict[f"Total errors {unit}"], unit_type=unit)
|
||||||
|
|
||||||
|
for unit in [UnitType.percentage, UnitType.requests]:
|
||||||
|
for device in ["Core", "Cache"]:
|
||||||
|
del stats_dict[f"{device} read errors {unit}"]
|
||||||
|
del stats_dict[f"{device} write errors {unit}"]
|
||||||
|
del stats_dict[f"{device} total errors {unit}"]
|
||||||
|
del stats_dict[f"Total errors {unit}"]
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return (
|
return (
|
||||||
f"Error stats:\n"
|
f"Error stats:\n"
|
||||||
@ -593,12 +626,6 @@ class ErrorStats:
|
|||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
return iter([getattr(self, stats_item) for stats_item in self.__dict__])
|
return iter([getattr(self, stats_item) for stats_item in self.__dict__])
|
||||||
|
|
||||||
def __sub__(self, other):
|
|
||||||
self.cache -= other.cache
|
|
||||||
self.core -= other.core
|
|
||||||
self.total_errors -= other.total_errors
|
|
||||||
return self
|
|
||||||
|
|
||||||
|
|
||||||
class BasicStatsChunk:
|
class BasicStatsChunk:
|
||||||
def __init__(self, stats_dict: dict, percentage_val: bool, device: str):
|
def __init__(self, stats_dict: dict, percentage_val: bool, device: str):
|
||||||
@ -620,12 +647,6 @@ class BasicStatsChunk:
|
|||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
return iter([getattr(self, stats_item) for stats_item in self.__dict__])
|
return iter([getattr(self, stats_item) for stats_item in self.__dict__])
|
||||||
|
|
||||||
def __sub__(self, other):
|
|
||||||
self.reads -= other.reads
|
|
||||||
self.writes -= other.writes
|
|
||||||
self.total -= other.total
|
|
||||||
return self
|
|
||||||
|
|
||||||
|
|
||||||
class BasicStatsChunkError:
|
class BasicStatsChunkError:
|
||||||
def __init__(self, stats_dict: dict, percentage_val: bool, device: str):
|
def __init__(self, stats_dict: dict, percentage_val: bool, device: str):
|
||||||
@ -647,12 +668,6 @@ class BasicStatsChunkError:
|
|||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
return iter([getattr(self, stats_item) for stats_item in self.__dict__])
|
return iter([getattr(self, stats_item) for stats_item in self.__dict__])
|
||||||
|
|
||||||
def __sub__(self, other):
|
|
||||||
self.reads -= other.reads
|
|
||||||
self.writes -= other.writes
|
|
||||||
self.total -= other.total
|
|
||||||
return self
|
|
||||||
|
|
||||||
|
|
||||||
def get_stat_value(stat_dict: dict, key: str):
|
def get_stat_value(stat_dict: dict, key: str):
|
||||||
idx = key.index("[")
|
idx = key.index("[")
|
||||||
@ -698,7 +713,10 @@ def _get_section_filters(filter: List[StatsFilter], io_class_stats: bool = False
|
|||||||
|
|
||||||
|
|
||||||
def get_stats_dict(
|
def get_stats_dict(
|
||||||
filter: List[StatsFilter], cache_id: int, core_id: int = None, io_class_id: int = None
|
filter: List[StatsFilter],
|
||||||
|
cache_id: int,
|
||||||
|
core_id: int = None,
|
||||||
|
io_class_id: int = None,
|
||||||
):
|
):
|
||||||
csv_stats = casadm.print_statistics(
|
csv_stats = casadm.print_statistics(
|
||||||
cache_id=cache_id,
|
cache_id=cache_id,
|
||||||
|
Loading…
Reference in New Issue
Block a user