Skip to content

Commit 3db61b6

Browse files
committed
ft-analyzer refactor statistical_model.py process_events
1 parent 80fe205 commit 3db61b6

1 file changed

Lines changed: 113 additions & 128 deletions

File tree

tools/ft-analyzer/ftanalyzer/models/statistical_model.py

Lines changed: 113 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -635,12 +635,6 @@ def setup_statsitic_objects(
635635
measure_start_time=start_time_offset,
636636
measure_end_time=end_time_offset,
637637
),
638-
# "ct_flow_rate": ContinuousCounter(
639-
# "flow rate",
640-
# sim,
641-
# measure_start_time=start_time_offset,
642-
# measure_end_time=end_time_offset,
643-
# ),
644638
"ct_cpu_usage": ContinuousCounter(
645639
"CPU usage in percent",
646640
sim,
@@ -696,14 +690,6 @@ def setup_statsitic_objects(
696690
measure_start_time=start_time_offset,
697691
measure_end_time=end_time_offset,
698692
),
699-
"tsc_flow_rate": TimeSeriesCounter(
700-
"flow rate",
701-
sim,
702-
start_time,
703-
end_time,
704-
measure_start_time=start_time_offset,
705-
measure_end_time=end_time_offset,
706-
),
707693
"tsc_cpu_usage": TimeSeriesCounter(
708694
"CPU usage in percent",
709695
sim,
@@ -750,7 +736,6 @@ def setup_statsitic_objects(
750736
"data_rate": ["ct_data_rate", "ct_data_rate_bibit", "tsc_data_rate"],
751737
"packet_rate": ["ct_packet_rate", "tsc_packet_rate"],
752738
"flow_count": ["ct_flow_count", "tsc_flow_count"],
753-
"flow_rate": ["ct_flow_rate", "tsc_flow_rate"],
754739
"percent_CPU": ["ct_cpu_usage", "tsc_cpu_usage"],
755740
"percent_MEM": ["ct_ram_usage", "tsc_mem_usage"],
756741
"export_rate_f": ["ct_export_rate_f", "tsc_export_rate_f"],
@@ -764,6 +749,79 @@ def setup_statsitic_objects(
764749
return (statistic_objects, metric_mapping)
765750

766751

752+
def _flush_event_data(
753+
one_packet_events: List[OnePacketFlow],
754+
current_data_rate: int,
755+
current_packet_rate: int,
756+
current_flows: int,
757+
statistic_objects: dict[str, StatisticObject],
758+
metric_mapping: dict[str, str],
759+
duration_s: float,
760+
simultaneous_events: List[Event],
761+
sim: SimState,
762+
last_export: int,
763+
):
764+
# aggregate OnePacketFlow events within this window
765+
one_packet_data_rate = sum(e.bytes for e in one_packet_events) * 8 / duration_s
766+
one_packet_packet_rate = sum(e.packets for e in one_packet_events) / duration_s
767+
one_packet_flows = np.uint64(sum(e.flows for e in one_packet_events))
768+
769+
# Compose final rates
770+
total_data_rate = one_packet_data_rate + current_data_rate
771+
total_packet_rate = one_packet_packet_rate + current_packet_rate
772+
total_flows = one_packet_flows + current_flows
773+
774+
update_statistic_objects(
775+
statistic_objects,
776+
metric_mapping,
777+
data_rate=total_data_rate,
778+
packet_rate=total_packet_rate,
779+
flow_count=total_flows,
780+
)
781+
782+
export_events: List[ExportEvent] = [
783+
e for e in simultaneous_events if isinstance(e, ExportEvent)
784+
]
785+
since_last_export: np.uint64 = sim.get_time_diff(last_export)
786+
if export_events:
787+
time_since_export_s = sim.convert_to_seconds(since_last_export)
788+
export_flows = sum(e.flows for e in export_events)
789+
export_bytes = sum(e.bytes for e in export_events)
790+
export_packets = len(export_events)
791+
export_flows_p_packet = export_flows / export_packets
792+
update_statistic_objects(
793+
statistic_objects,
794+
metric_mapping,
795+
export_rate_f=export_flows / time_since_export_s,
796+
export_rate_b=export_bytes / time_since_export_s,
797+
export_rate_p=export_packets / time_since_export_s,
798+
export_flows_p_packet=export_flows_p_packet,
799+
)
800+
last_export = sim.get_time()
801+
elif since_last_export >= 1000:
802+
# use 0 as datapoint every second to register absence of exports
803+
update_statistic_objects(
804+
statistic_objects,
805+
metric_mapping,
806+
export_rate_f=0,
807+
export_rate_b=0,
808+
export_rate_p=0,
809+
export_flows_p_packet=0.0,
810+
)
811+
last_export = sim.get_time()
812+
813+
host_stats_event: HostStatsEvent = next(
814+
(e for e in simultaneous_events if isinstance(e, HostStatsEvent)),
815+
None,
816+
)
817+
if host_stats_event:
818+
update_statistic_objects(
819+
statistic_objects, metric_mapping, **host_stats_event.row._asdict()
820+
)
821+
822+
return last_export
823+
824+
767825
def process_events(
768826
event_queue: Iterable[Event],
769827
statistic_objects: dict[str, StatisticObject],
@@ -780,10 +838,9 @@ def process_events(
780838
"""
781839

782840
one_packet_events: list[OnePacketFlow] = []
783-
current_data_rate = 0.0
784-
current_packet_rate = 0.0
785-
current_flow_count = np.uint64(0)
786-
current_flow_rate = 0.0
841+
current_data_rate = 0
842+
current_packet_rate = 0
843+
current_flows = 0
787844

788845
# Prime the iterator
789846
event_iter = iter(event_queue)
@@ -806,81 +863,25 @@ def process_events(
806863
# Compute the duration between the last time and the current group of events
807864
duration_ms = sim.get_time_diff(last_time)
808865
duration_s = sim.convert_to_seconds(duration_ms)
809-
since_last_export: np.uint64 = sim.get_time_diff(last_export)
810866

811867
# Only advance stats if time progressed
812868
if (
813869
duration_ms > 0
814870
and not all_instance_of(simultaneous_events, OnePacketFlow)
815871
or duration_ms > 100
816872
):
817-
# aggregate OnePacketFlow events within this window
818-
total_bytes = sum(e.bytes for e in one_packet_events)
819-
total_packets = sum(e.packets for e in one_packet_events)
820-
total_flows = np.uint64(sum(e.flows for e in one_packet_events))
821-
822-
singleton_data_rate = (
823-
(total_bytes * 8) / duration_s if duration_s > 0 else 0.0
824-
)
825-
singleton_packet_rate = (
826-
total_packets / duration_s if duration_s > 0 else 0.0
827-
)
828-
829-
singleton_flow_rate = total_flows / duration_s if duration_s > 0 else 0.0
830-
831-
# Compose final rates
832-
total_data_rate = current_data_rate + singleton_data_rate
833-
total_packet_rate = current_packet_rate + singleton_packet_rate
834-
total_flow_count = current_flow_count + total_flows
835-
total_flow_rate = current_flow_rate + singleton_flow_rate
836-
837-
update_statistic_objects(
873+
last_export = _flush_event_data(
874+
one_packet_events,
875+
current_data_rate,
876+
current_packet_rate,
877+
current_flows,
838878
statistic_objects,
839879
metric_mapping,
840-
data_rate=total_data_rate,
841-
packet_rate=total_packet_rate,
842-
flow_count=total_flow_count,
843-
flow_rate=total_flow_rate,
880+
duration_s,
881+
simultaneous_events,
882+
sim,
883+
last_export,
844884
)
845-
846-
export_events: List[ExportEvent] = [
847-
e for e in simultaneous_events if isinstance(e, ExportEvent)
848-
]
849-
if export_events:
850-
time_since_export_s = sim.convert_to_seconds(since_last_export)
851-
export_flows = sum(e.flows for e in export_events)
852-
export_bytes = sum(e.bytes for e in export_events)
853-
export_packets = len(export_events)
854-
export_flows_p_packet = export_flows / export_packets
855-
update_statistic_objects(
856-
statistic_objects,
857-
metric_mapping,
858-
export_rate_f=export_flows / time_since_export_s,
859-
export_rate_b=export_bytes / time_since_export_s,
860-
export_rate_p=export_packets / time_since_export_s,
861-
export_flows_p_packet=export_flows_p_packet,
862-
)
863-
last_export = sim.get_time()
864-
elif since_last_export >= 1000:
865-
update_statistic_objects(
866-
statistic_objects,
867-
metric_mapping,
868-
export_rate_f=0.0,
869-
export_rate_b=0.0,
870-
export_rate_p=0.0,
871-
export_flows_p_packet=0.0,
872-
)
873-
last_export = sim.get_time()
874-
875-
host_stats_event: HostStatsEvent = next(
876-
(e for e in simultaneous_events if isinstance(e, HostStatsEvent)),
877-
None,
878-
)
879-
if host_stats_event:
880-
update_statistic_objects(
881-
statistic_objects, metric_mapping, **host_stats_event.row._asdict()
882-
)
883-
884885
# reset one-packet events after processing
885886
one_packet_events.clear()
886887
# move forward in time
@@ -895,8 +896,10 @@ def process_events(
895896
else:
896897
current_data_rate += e.data_rate
897898
current_packet_rate += e.packet_rate
898-
current_flow_rate += e.flow_rate
899-
current_flow_count += e.flows
899+
current_flows += e.flows
900+
901+
current_data_rate = max(0, current_data_rate)
902+
current_packet_rate = max(0, current_packet_rate)
900903

901904
sim.set_time(event.time)
902905
simultaneous_events = [event]
@@ -905,40 +908,19 @@ def process_events(
905908
duration_ms = sim.get_time_diff(last_time)
906909
duration_s = sim.convert_to_seconds(duration_ms)
907910

908-
if duration_s > 0:
909-
# aggregate OnePacketFlow events within this window
910-
total_bytes = sum(e.bytes for e in one_packet_events)
911-
total_packets = sum(e.packets for e in one_packet_events)
912-
total_flows = np.uint64(sum(e.flows for e in one_packet_events))
913-
914-
singleton_data_rate = (total_bytes * 8) / duration_s if duration_s > 0 else 0.0
915-
singleton_packet_rate = total_packets / duration_s if duration_s > 0 else 0.0
916-
917-
singleton_flow_rate = total_flows / duration_s if duration_s > 0 else 0.0
918-
919-
# Compose final rates
920-
total_data_rate = current_data_rate + singleton_data_rate
921-
total_packet_rate = current_packet_rate + singleton_packet_rate
922-
total_flow_count = current_flow_count + total_flows
923-
total_flow_rate = current_flow_rate + singleton_flow_rate
924-
925-
update_statistic_objects(
911+
if duration_ms > 0:
912+
_flush_event_data(
913+
one_packet_events,
914+
current_data_rate,
915+
current_packet_rate,
916+
current_flows,
926917
statistic_objects,
927918
metric_mapping,
928-
data_rate=total_data_rate,
929-
packet_rate=total_packet_rate,
930-
flow_count=total_flow_count,
931-
flow_rate=total_flow_rate,
932-
)
933-
934-
host_stats_event: HostStatsEvent = next(
935-
(e for e in simultaneous_events if isinstance(e, HostStatsEvent)),
936-
None,
919+
duration_s,
920+
simultaneous_events,
921+
sim,
922+
last_export,
937923
)
938-
if host_stats_event:
939-
update_statistic_objects(
940-
statistic_objects, metric_mapping, **host_stats_event.row._asdict()
941-
)
942924

943925

944926
def update_statistic_objects(
@@ -974,9 +956,15 @@ def _validate_helper(
974956
):
975957
all_flow_masks = {}
976958
values: List[dict] = []
959+
start_time = float("inf")
960+
end_time = float("-inf")
961+
977962
for chunk in pd.read_csv(
978963
flows_file, dtype=StatisticalModel.CSV_COLUMN_TYPES, chunksize=chunksize
979964
):
965+
start_time = min(start_time, chunk["START_TIME"].min())
966+
end_time = max(end_time, chunk["END_TIME"].max())
967+
980968
if complement:
981969
chunk = chunk[~(reduce(operator.or_, flow_masks))].reset_index(drop=True)
982970
for i, rule in zip(range(len(rules)), rules):
@@ -992,15 +980,6 @@ def _validate_helper(
992980
if len({m.key for m in rule.metrics}) != len(rule.metrics):
993981
raise SMException(f"Rule contains duplicated metrics: {rule.metrics}")
994982

995-
if is_ref:
996-
duration = (
997-
generator_stats.end_time - generator_stats.start_time + 1
998-
) / 1000
999-
else:
1000-
duration = (
1001-
flows["END_TIME"].max() - flows["START_TIME"].min() + 1
1002-
) / 1000
1003-
1004983
for metric in rule.metrics:
1005984
match metric.key:
1006985
case SMMetricType.FLOWS:
@@ -1010,7 +989,7 @@ def _validate_helper(
1010989
case SMMetricType.PPS:
1011990
value = 0 # later calculated
1012991
case SMMetricType.DURATION:
1013-
value = duration
992+
value = 0 # later calculated
1014993
case _:
1015994
value = flows[metric.key.value].sum()
1016995

@@ -1025,7 +1004,13 @@ def _validate_helper(
10251004
values[i] = values_dict
10261005

10271006
for values_dict in values:
1028-
duration = values_dict[SMMetricType.DURATION]
1007+
if is_ref:
1008+
duration = (
1009+
generator_stats.end_time - generator_stats.start_time + 1
1010+
) / 1000
1011+
else:
1012+
duration = (end_time - start_time + 1) / 1000
1013+
values_dict[SMMetricType.DURATION] = duration
10291014
values_dict[SMMetricType.MBPS] = (
10301015
values_dict[SMMetricType.BYTES] / duration / 10**6
10311016
)

0 commit comments

Comments
 (0)