@@ -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+
767825def 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
944926def 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