-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCompute.py
More file actions
executable file
·2659 lines (2140 loc) · 128 KB
/
Compute.py
File metadata and controls
executable file
·2659 lines (2140 loc) · 128 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
import re
import requests
import json
import time
import matplotlib.pyplot as plt
from datetime import datetime, timedelta,timezone
import pandas as pd
from collections import defaultdict
from mpl_toolkits.mplot3d.art3d import line_2d_to_3d
from scipy.interpolate import make_interp_spline
from config import db_url_get_time
from config import k3s_config_file
from config import onos_ip_address
from config import Prometheus_ip_address
from kubernetes import client, config
import openai
import os
import logging
openai.api_key = "Your_key"
# Global variables
output_file = "time_factors.json" # Changed to relative path like your working code
summary_output_file = "RT_SFC.json"
average_rt_file = "avg_RT.json"
timestamps = []
response_times = []
estimated_rts = [] # Initialize estimated_rts here to avoid unresolved reference
average_response_times = []
violation_estimated_rts = [] # List to store estimated RTs where violations occur
min_threshold_estimated_rts = []
intent = 3
min_threshold= 1
alpha = 0.02 # Smoothing factor for Estimated RT
detected_violation_timestamp = None
detected_min_threshold_timestamp = None
violation_handled_time = None
min_threshold_handled_time = None
violation_handled = False
min_threshold_handled = False
retries = 1 # Global variable for controlling the cycle
fig_size = (10, 6)
fig, ax = plt.subplots(figsize=fig_size)
window_size = 30
# Set up logging configuration
logging.basicConfig(
filename='A-main-api4-movingAVG-loop-real-time-lifespan-main-log', # Log to the file named "experiment_logs"
level=logging.INFO, # Log level: INFO (you can also use DEBUG for more detailed logging)
format='%(asctime)s - %(levelname)s - %(message)s', # Log format
datefmt='%Y-%m-%d %H:%M:%S' # Date format
)
# Get cluster info from k3s api
#################################################################
#################################################################
#################################################################
def get_pod_placement_and_replicas():
# Specify path to K3s configuration file
logging.info("=======calling k3s api to collect the cluster details (start)=======")
k3s_config_path = k3s_config_file
# Check if the configuration file exists and is readable
if os.path.exists(k3s_config_path):
if os.access(k3s_config_path, os.R_OK):
config.load_kube_config(config_file=k3s_config_path)
# Create Kubernetes API clients
core_v1_api = client.CoreV1Api()
apps_v1_api = client.AppsV1Api()
# Retrieve list of nodes
node_list = core_v1_api.list_node()
# Retrieve list of pods
pod_list = core_v1_api.list_pod_for_all_namespaces(watch=False)
# Retrieve list of deployments
deployment_list = apps_v1_api.list_deployment_for_all_namespaces(watch=False)
# Initialize a dictionary to store the data
data = {}
important_data = {}
# Iterate through nodes and collect their resource limits
nodes_data = []
for node in node_list.items:
node_info = {
"name": node.metadata.name,
"capacity": {
"cpu": node.status.capacity.get('cpu', 'Not set'),
"memory": node.status.capacity.get('memory', 'Not set')
},
"allocatable": {
"cpu": node.status.allocatable.get('cpu', 'Not set'),
"memory": node.status.allocatable.get('memory', 'Not set')
}
}
nodes_data.append(node_info)
data["nodes"] = nodes_data
important_data["nodes"] = nodes_data # Include all nodes in important data as well
print('node details have been collected')
logging.info('node details have been collected')
# Iterate through pods and collect their placement and resource limits
pods_data = []
important_pods_data = []
for pod in pod_list.items:
pod_info = {
"name": pod.metadata.name,
"namespace": pod.metadata.namespace, # Keep namespace in original data
"node": pod.spec.node_name,
"resources": {
"cpu_limit": pod.spec.containers[0].resources.limits.get('cpu',
'Not set') if pod.spec.containers and
pod.spec.containers[
0].resources and
pod.spec.containers[
0].resources.limits else "Not set",
"memory_limit": pod.spec.containers[0].resources.limits.get('memory',
'Not set') if pod.spec.containers and
pod.spec.containers[
0].resources and
pod.spec.containers[
0].resources.limits else "Not set"
}
}
pods_data.append(pod_info)
# For important pods, exclude namespace
if pod.metadata.name.startswith("microservice"):
important_pod_info = {key: value for key, value in pod_info.items() if key != "namespace"}
important_pods_data.append(important_pod_info)
data["pods"] = pods_data
important_data["pods"] = important_pods_data
print('pod details have been collected')
logging.info('pod details have been collected')
# Initialize important_deployments_data
important_deployments_data = []
# Iterate through deployments and collect their replica count
deployments_data = []
for deployment in deployment_list.items:
deployment_info = {
"name": deployment.metadata.name,
"namespace": deployment.metadata.namespace, # Keep namespace in original data
"replicas": deployment.spec.replicas
}
deployments_data.append(deployment_info)
# For important deployments, exclude namespace
if "microservice" in deployment.metadata.name:
important_deployment_info = {key: value for key, value in deployment_info.items() if
key != "namespace"}
important_deployments_data.append(important_deployment_info)
data["deployments"] = deployments_data
important_data["deployments"] = important_deployments_data
print('deployment details have been collected')
logging.info('deployment details have been collected')
# Wrap the data in an outer object with the key "Kubernetes"
kubernetes_data = {"Kubernetes": data}
# Write the data to a JSON file
with open("k3s_cluster_info_original.json", "w") as file:
json.dump(kubernetes_data, file, indent=4)
print(
"all details, including node pod and deployments, saved into the file named k3s_cluster_info_original.json")
logging.info(
"all details, including node pod and deployments, saved into the file named k3s_cluster_info_original.json")
# Wrap and save the important data (without namespace field)
kubernetes_important_data = {"Kubernetes": important_data}
with open("k3s_cluster_info_important.json", "w") as file:
json.dump(kubernetes_important_data, file, indent=4)
print("important details saved into the file named k3s_cluster_info_important.json")
logging.info("important details saved into the file named k3s_cluster_info_important.json")
else:
print("Insufficient permissions to read the configuration file.")
logging.error("Insufficient permissions to read the configuration file.")
else:
print("K3s configuration file does not exist.")
logging.error("K3s configuration file does not exist.")
logging.info("=======calling k3s api to collect the cluster details (end)=======")
# Get network info from onos api
#################################################################
#################################################################
#################################################################
def make_request(url):
headers = {'Authorization': 'Basic b25vczpyb2Nrcw=='}
response = requests.get(url, headers=headers)
return response.json()
# get hosts info from Rest API
def get_hosts():
url = f"http://{onos_ip_address}/onos/v1/hosts"
parsed = make_request(url)
# with open('hosts.json', 'w') as f:
# json.dump(parsed, f, indent=4)
# print('\n**************************************************\n')
# print(f"\033[1;30;42m >>>>> Number of hosts, including mininet hosts: {len(parsed['hosts'])} \n")
# Filter out hosts with MAC addresses starting with '00:00:00:00:00'
filtered_hosts = [host for host in parsed['hosts'] if not host['mac'].startswith('00:00:00:00:00')]
# Print the filtered connectivity information
# print('\033[1;30;44m >>>>> Connectivity between switches and K8-hosts \n')
# for host in filtered_hosts:
# print(host['locations'][0], host['ipAddresses'][0])
# Save the filtered hosts data to 'onos_hosts.json'
with open('onos_hosts.json', 'w') as f:
json.dump({'hosts': filtered_hosts}, f, indent=4)
return parsed
# get switches connectivity info from Rest API
def get_switchLinks():
url = f"http://{onos_ip_address}/onos/v1/topology/clusters/0/links"
parsed = make_request(url)
# print('\033[1;30;46m >>>>> Connectivity between switches')
# for links in parsed['links']:
# print(links)
with open('onos_links.json', 'w') as f:
json.dump(parsed, f, indent=4)
return parsed
# New function to create 'onos_hosts_important.json'- without extra details which are not needed.
def create_important_hosts_json():
url = f"http://{onos_ip_address}/onos/v1/hosts"
parsed = make_request(url)
# Filter out hosts with MAC addresses starting with '00:00:00:00:00'
filtered_hosts = [host for host in parsed['hosts'] if not host['mac'].startswith('00:00:00:00:00')]
# Create a new file 'onos_hosts_important.json' with only 'mac', 'ipAddresses', and 'locations' keys
important_hosts = [{'mac': host['mac'], 'ipAddresses': host['ipAddresses'], 'locations': host['locations']} for host
in filtered_hosts]
with open('onos_hosts_important.json', 'w') as f:
json.dump({'hosts': important_hosts}, f, indent=4)
# New function to create 'onos_links_important.json' without 'type' and 'state'
#################################################################################
def create_important_links_json():
url = f"http://{onos_ip_address}/onos/v1/topology/clusters/0/links"
parsed = make_request(url)
# Filter out 'type' and 'state' from each link
important_links = [{'src': link['src'], 'dst': link['dst']} for link in parsed['links']]
# Save the modified links data to 'onos_links_important.json'
with open('onos_links_important.json', 'w') as f:
json.dump({'links': important_links}, f, indent=4)
# Get monitoring data from Prometheus api
#################################################################
#################################################################
#################################################################
def query_prometheus_for_violation_data():
logging.info("======= calling prometheus api to collect monitoring data (start)=======")
# Define the Prometheus server URL
prometheus_url = f"http://{Prometheus_ip_address}/api/v1/"
# Use the detected violation timestamp from process_response_times
if detected_violation_timestamp is None:
print("No violation detected, skipping Prometheus data collection.")
logging.info("No violation detected, skipping Prometheus data collection.")
return
# Convert violation timestamp to Unix time
violation_timestamp = int(datetime.strptime(detected_violation_timestamp, '%Y-%m-%d %H:%M:%S').timestamp())
monitor_window_size = 30 # 30 requests per window
monitor_interval = '10s'
numeric_value_monitor_interval = int(monitor_interval[:-1]) # Convert '10s' to 10 (seconds)
# Queries for CPU, Memory, and traffic
queries = {
'cpu': 'sflow_cpu_utilization',
'mem': 'sflow_mem_utilization',
'ifin': 'sflow_ifinutilization',
'ifout': 'sflow_ifoututilization'
}
# Function to retrieve all unique ifname values for traffic queries
def get_ifnames():
query = 'sflow_ifoututilization'
params = {
'query': query,
'start': violation_timestamp - 900,
'end': violation_timestamp + 900,
'step': monitor_interval
}
response = requests.get(f"{prometheus_url}query_range", params=params)
if response.status_code == 200:
data = response.json()
if data['status'] == 'success':
results = data['data']['result']
ifnames = set(result['metric'].get('ifname') for result in results if 'ifname' in result['metric'])
return list(ifnames)
return []
# Function to calculate window start times for queries
def calculate_window_times(violation_timestamp, monitor_window_size):
step_interval = numeric_value_monitor_interval # seconds step interval
window_duration = monitor_window_size * step_interval
third_window_start = violation_timestamp - window_duration # Start of the third window (containing violation)
second_window_start = third_window_start - window_duration # Start of the second window
first_window_start = second_window_start - window_duration # Start of the first window
return first_window_start, second_window_start
# Function to query Prometheus and save the data
def query_and_save_averages(query_name, filename, avg_filename, ifnames=None):
output = {}
avg_output = {}
if ifnames:
for ifname in ifnames:
query = queries[query_name] + f'{{ifname="{ifname}"}}'
params = {
'query': query,
'start': violation_timestamp - 900, # 15 minutes before violation
'end': violation_timestamp + 900, # 15 minutes after violation
'step': monitor_interval
}
response = requests.get(f"{prometheus_url}query_range", params=params)
if response.status_code == 200:
data = response.json()
if data['status'] == 'success':
results = data['data']['result']
for result in results:
host = result['metric'].get('host', ifname)
output[host] = []
avg_output[host] = []
values = result['values']
# Calculate averages every 20 values
for i in range(0, len(values), 20):
subset = values[i:i + 20]
avg_value = sum(float(v[1]) for v in subset) / len(subset)
avg_timestamp = datetime.utcfromtimestamp(subset[-1][0]).strftime('%Y-%m-%d %H:%M:%S')
avg_output[host].append({
"timestamp": avg_timestamp,
query_name + "_avg_utilization": avg_value
})
# Save original data
for value in values:
timestamp = datetime.utcfromtimestamp(value[0]).strftime('%Y-%m-%d %H:%M:%S')
metric_value = value[1]
# Use the host field as the key (fallback to "unknown" if missing)
output_key = result['metric'].get('host', 'unknown') # Ensure 'host' is used as key
if output_key not in output:
output[output_key] = []
# Append the data, including the entire 'metric' dictionary
output[output_key].append({
"timestamp": timestamp,
query_name + "_utilization": metric_value,
"metrics": result['metric'] # Include all metadata from 'metric'
})
else:
query = queries[query_name]
params = {
'query': query,
'start': violation_timestamp - 900, # 15 minutes before violation
'end': violation_timestamp + 900, # 15 minutes after violation
'step': monitor_interval
}
response = requests.get(f"{prometheus_url}query_range", params=params)
if response.status_code == 200:
data = response.json()
if data['status'] == 'success':
results = data['data']['result']
for result in results:
host = result['metric'].get('host', 'unknown')
output[host] = []
avg_output[host] = []
values = result['values']
# Calculate averages every 20 values
for i in range(0, len(values), 20):
subset = values[i:i + 20]
avg_value = sum(float(v[1]) for v in subset) / len(subset)
avg_timestamp = datetime.utcfromtimestamp(subset[-1][0]).strftime('%Y-%m-%d %H:%M:%S')
avg_output[host].append({
"timestamp": avg_timestamp,
query_name + "_avg_utilization": avg_value
})
# Save original data
for value in values:
timestamp = datetime.utcfromtimestamp(value[0]).strftime('%Y-%m-%d %H:%M:%S')
metric_value = value[1]
output[host].append({
"timestamp": timestamp,
query_name + "_utilization": metric_value
})
else:
print(f"Error querying Prometheus API: {response.status_code}")
logging.error(f"Error querying Prometheus API: {response.status_code}")
return
with open(filename, 'w') as json_file:
json.dump(output, json_file, indent=4)
with open(avg_filename, 'w') as json_file:
json.dump(avg_output, json_file, indent=4)
print(f"Data has been saved to {filename} and averages to {avg_filename}")
logging.info(f"Data has been saved to {filename} and averages to {avg_filename}")
# Collect and save data for three windows before the violation
def before_violation(query_name, output_filename, ifnames=None):
output = {}
# Calculate start and end times for the first two windows before the violation
first_window_start, second_window_start = calculate_window_times(violation_timestamp, monitor_window_size)
end_time = violation_timestamp - (
monitor_window_size * numeric_value_monitor_interval) # End at the start of the third window
# For ifin and ifout queries, apply ifnames, otherwise proceed normally
if query_name in ['ifin', 'ifout'] and ifnames:
for ifname in ifnames:
query = queries[query_name] + f'{{ifname="{ifname}"}}'
params = {
'query': query,
'start': first_window_start,
'end': end_time,
'step': monitor_interval
}
response = requests.get(f"{prometheus_url}query_range", params=params)
if response.status_code == 200:
data = response.json()
if data['status'] == 'success':
results = data['data']['result']
for result in results:
host = result['metric'].get('host', ifname)
values = result['values']
# Average the data from the first two windows
all_values = [float(v[1]) for v in values[:2 * monitor_window_size]]
avg_value = sum(all_values) / len(all_values)
# Save the single averaged value in the output
output[host] = {
"timestamp": detected_violation_timestamp,
f"{query_name}_avg_before_violation": avg_value
}
else:
print(f"Error querying Prometheus API for {ifname}: {response.status_code}")
logging.error(f"Error querying Prometheus API for {ifname}: {response.status_code}")
else:
query = queries[query_name]
params = {
'query': query,
'start': first_window_start,
'end': end_time,
'step': monitor_interval
}
response = requests.get(f"{prometheus_url}query_range", params=params)
if response.status_code == 200:
data = response.json()
if data['status'] == 'success':
results = data['data']['result']
for result in results:
host = result['metric'].get('host', 'unknown')
values = result['values']
# Average the data from the first two windows
all_values = [float(v[1]) for v in values[:2 * monitor_window_size]]
avg_value = sum(all_values) / len(all_values)
# Save the single averaged value in the output
output[host] = {
"timestamp": detected_violation_timestamp,
f"{query_name}_avg_before_violation": avg_value
}
else:
print(f"Error querying Prometheus API: {response.status_code}")
logging.error(f"Error querying Prometheus API: {response.status_code}")
# Save the output data to a JSON file
with open(output_filename, 'w') as json_file:
json.dump(output, json_file, indent=4)
print(f"Single averaged data has been saved to {output_filename}")
logging.info(f"Single averaged data has been saved to {output_filename}")
# Function to query Prometheus for data during the violation window
def violation(query_name, output_filename, ifnames=None):
output = {}
# Define the window size and calculate the third window, which contains the violation
step_interval = numeric_value_monitor_interval # seconds step interval
window_duration = monitor_window_size * step_interval
# The third window starts immediately before the violation timestamp and lasts for one window duration
third_window_start = violation_timestamp - window_duration
third_window_end = violation_timestamp
# For ifin and ifout queries, apply ifnames, otherwise proceed normally
if query_name in ['ifin', 'ifout'] and ifnames:
for ifname in ifnames:
query = queries[query_name] + f'{{ifname="{ifname}"}}'
params = {
'query': query,
'start': third_window_start,
'end': third_window_end,
'step': monitor_interval
}
response = requests.get(f"{prometheus_url}query_range", params=params)
if response.status_code == 200:
data = response.json()
if data['status'] == 'success':
results = data['data']['result']
for result in results:
host = result['metric'].get('host', ifname)
values = result['values']
# Calculate the average value for this violation window
utilization_values = [float(v[1]) for v in values]
avg_utilization = sum(utilization_values) / len(
utilization_values) if utilization_values else 0
# Save the single averaged value in the output
output[host] = {
"timestamp": detected_violation_timestamp,
f"{query_name}_avg_utilization_violation": avg_utilization
}
else:
print(f"Error querying Prometheus API for {ifname}: {response.status_code}")
logging.error(f"Error querying Prometheus API for {ifname}: {response.status_code}")
else:
query = queries[query_name]
params = {
'query': query,
'start': third_window_start,
'end': third_window_end,
'step': monitor_interval
}
response = requests.get(f"{prometheus_url}query_range", params=params)
if response.status_code == 200:
data = response.json()
if data['status'] == 'success':
results = data['data']['result']
for result in results:
host = result['metric'].get('host', 'unknown')
values = result['values']
# Calculate the average value for this violation window
utilization_values = [float(v[1]) for v in values]
avg_utilization = sum(utilization_values) / len(utilization_values) if utilization_values else 0
# Save the single averaged value in the output
output[host] = {
"timestamp": detected_violation_timestamp,
f"{query_name}_avg_utilization_violation": avg_utilization
}
else:
print(f"Error querying Prometheus API: {response.status_code}")
logging.error(f"Error querying Prometheus API: {response.status_code}")
# Save the output data to a JSON file
with open(output_filename, 'w') as json_file:
json.dump(output, json_file, indent=4)
print(f"Averaged violation window data has been saved to {output_filename}")
logging.info(f"Averaged violation window data has been saved to {output_filename}")
# Collect and save data for two windows after the violation
def after_violation(query_name, output_filename, ifnames=None):
output = {}
# Calculate start and end times for two windows after the violation
step_interval = numeric_value_monitor_interval # seconds step interval
window_duration = monitor_window_size * step_interval
first_window_start = violation_timestamp + window_duration
second_window_start = first_window_start + window_duration
end_time = second_window_start + window_duration
# For ifin and ifout queries, apply ifnames, otherwise proceed normally
if query_name in ['ifin', 'ifout'] and ifnames:
for ifname in ifnames:
query = queries[query_name] + f'{{ifname="{ifname}"}}'
params = {
'query': query,
'start': first_window_start,
'end': end_time,
'step': monitor_interval
}
response = requests.get(f"{prometheus_url}query_range", params=params)
if response.status_code == 200:
data = response.json()
if data['status'] == 'success':
results = data['data']['result']
for result in results:
host = result['metric'].get('host', ifname)
values = result['values']
# Average the data from the two windows after the violation
all_values = [float(v[1]) for v in values[:2 * monitor_window_size]]
avg_value = sum(all_values) / len(all_values)
# Save the single averaged value in the output
output[host] = {
"timestamp": detected_violation_timestamp,
f"{query_name}_avg_after_violation": avg_value
}
else:
print(f"Error querying Prometheus API for {ifname}: {response.status_code}")
logging.error("Error querying Prometheus API for {ifname}: {response.status_code}")
else:
query = queries[query_name]
params = {
'query': query,
'start': first_window_start,
'end': end_time,
'step': monitor_interval
}
response = requests.get(f"{prometheus_url}query_range", params=params)
if response.status_code == 200:
data = response.json()
if data['status'] == 'success':
results = data['data']['result']
for result in results:
host = result['metric'].get('host', 'unknown')
values = result['values']
# Average the data from the two windows after the violation
all_values = [float(v[1]) for v in values[:2 * monitor_window_size]]
avg_value = sum(all_values) / len(all_values)
# Save the single averaged value in the output
output[host] = {
"timestamp": detected_violation_timestamp,
f"{query_name}_avg_after_violation": avg_value
}
else:
print(f"Error querying Prometheus API: {response.status_code}")
logging.error(f"Error querying Prometheus API: {response.status_code}")
# Save the output data to a JSON file
with open(output_filename, 'w') as json_file:
json.dump(output, json_file, indent=4)
print(f"Data after violation has been saved to {output_filename}")
logging.info(f"Data after violation has been saved to {output_filename}")
# Combine the before and after violation data
def combine_before_after_violation(before_file, after_file, output_file):
with open(before_file, 'r') as bf:
before_data = json.load(bf)
with open(after_file, 'r') as af:
after_data = json.load(af)
combined_data = {}
for key, before_values in before_data.items():
combined_data[key] = {}
if key in after_data:
for field, value in before_values.items():
if field != "timestamp":
after_field = field.replace("_before", "_after")
if after_field in after_data[key]:
combined_data[key][field] = value
combined_data[key][after_field] = after_data[key].get(after_field)
with open(output_file, 'w') as output:
json.dump(combined_data, output, indent=4)
print(f"Combined data has been saved to {output_file}")
logging.info(f"Combined data has been saved to {output_file}")
def combined_violation_and_previolation(before_filename, violation_filename, output_filename):
# Helper function to load JSON data from a file
def load_json_file(filename):
with open(filename, 'r') as json_file:
return json.load(json_file)
# Helper function to save combined data to a JSON file
def save_combined_data(combined_data, output_filename):
with open(output_filename, 'w') as json_file:
json.dump(combined_data, json_file, indent=4)
print(f"Combined data has been saved to {output_filename}")
logging.info(f"Combined data has been saved to {output_filename}")
# Combine data from before violation and during the violation
def combine_before_and_violation(before_filename, violation_filename):
before_data = load_json_file(before_filename)
violation_data = load_json_file(violation_filename)
combined_data = {}
# Combine the two datasets
for host, before_values in before_data.items():
combined_data[host] = {key: value for key, value in before_values.items() if
key != "timestamp"} # Exclude timestamp field
if host in violation_data:
for field, value in violation_data[host].items():
if field != "timestamp": # Exclude the timestamp field
combined_data[host][field.replace('_avg_utilization',
'_avg_utilization_violation')] = value # Add the violation data
return combined_data
# Combine the data and save it
combined_data = combine_before_and_violation(before_filename, violation_filename)
save_combined_data(combined_data, output_filename)
#>>>>>new function as octet-start
def octet(output_in_filename, output_out_filename):
output_in = {}
output_out = {}
# Define queries for inoctets and outoctets
queries = {
'inbyte': 'sflow_ifinoctets', # "inbyte" for inoctets
'outbyte': 'sflow_ifoutoctets' # "outbyte" for outoctets
}
# Query Prometheus for octet metrics
for query_type, query_name in queries.items():
output = output_in if query_type == 'inbyte' else output_out
query = query_name
params = {
'query': query,
'start': violation_timestamp - 900,
'end': violation_timestamp + 900,
'step': monitor_interval
}
response = requests.get(f"{prometheus_url}query_range", params=params)
if response.status_code == 200:
data = response.json()
if data['status'] == 'success':
results = data['data']['result']
for result in results:
host = result['metric'].get('host', 'unknown')
link = result['metric'].get('link', 'unknown')
ifname = result['metric'].get('ifname', 'unknown')
values = result['values']
# Save the relevant data in the output
for value in values:
timestamp = datetime.utcfromtimestamp(value[0]).strftime(
'%Y-%m-%d %H:%M:%S') # Convert to UTC timestamp
metric_value = float(value[1]) # Convert value to float
output_key = f"{host}_{ifname}"
if output_key not in output:
output[output_key] = {
"host": host,
"ifname": ifname,
"link": link,
"data": []
}
output[output_key]["data"].append({
"timestamp": timestamp,
"value": metric_value # Keep "value" for raw data
})
else:
print(f"Error querying Prometheus API: {response.status_code}")
logging.error(f"Error querying Prometheus API: {response.status_code}")
# Save the initial unfiltered data
with open(output_in_filename, 'w') as json_file:
json.dump(output_in, json_file, indent=4)
with open(output_out_filename, 'w') as json_file:
json.dump(output_out, json_file, indent=4)
print(f"Octet data has been saved to {output_in_filename} and {output_out_filename}")
logging.info(f"Octet data has been saved to {output_in_filename} and {output_out_filename}")
# Function to filter and simplify data
def filter_and_simplify(data, query_type):
simplified_data = []
for key, value in data.items():
# Include only if "link" is not "unknown"
if value.get("link", "unknown") != "unknown":
for entry in value["data"]:
# Debugging: Print entry to verify structure
#print(f"Processing entry: {entry}")
#logging.debug(f"Processing entry: {entry}")
simplified_data.append({
"timestamp": entry["timestamp"],
f"{query_type}_value": entry["value"], # Map "value" to "inbyte_value" or "outbyte_value"
"host": value.get("host", "unknown"),
"ifname": value.get("ifname", "unknown")
})
return simplified_data
# Filter and simplify input and output data separately
filtered_in_data = filter_and_simplify(output_in, "inbyte")
filtered_out_data = filter_and_simplify(output_out, "outbyte")
# Save the filtered data into separate files
filtered_in_filename = "monitor_filtered_ifinbytes.json"
filtered_out_filename = "monitor_filtered_ifoutbytes.json"
with open(filtered_in_filename, 'w') as json_file:
json.dump(filtered_in_data, json_file, indent=4)
with open(filtered_out_filename, 'w') as json_file:
json.dump(filtered_out_data, json_file, indent=4)
print(f"Filtered and simplified in-byte data has been saved to {filtered_in_filename}")
logging.info(f"Filtered and simplified in-byte data has been saved to {filtered_in_filename}")
print(f"Filtered and simplified out-byte data has been saved to {filtered_out_filename}")
logging.info(f"Filtered and simplified out-byte data has been saved to {filtered_out_filename}")
#>>>>>>>>>>>>>>>>previolation
def filter_previolation_octets(filtered_file, output_file, query_type):
# Ensure the global detected_violation_timestamp is set
global detected_violation_timestamp
if detected_violation_timestamp is None:
print("No violation detected. Skipping pre-violation data collection for octets.")
logging.info("No violation detected. Skipping pre-violation data collection for octets.")
return
# Convert detected_violation_timestamp to Unix time
violation_timestamp = int(datetime.strptime(detected_violation_timestamp, '%Y-%m-%d %H:%M:%S').timestamp())
# Define start and end of the pre-violation window (10 minutes before violation)
pre_violation_start = violation_timestamp - 600 # 10 minutes = 600 seconds
pre_violation_end = violation_timestamp # Ends at the violation timestamp
# Load the filtered octet data
with open(filtered_file, 'r') as json_file:
data = json.load(json_file)
# Filter data based on the pre-violation window
filtered_data = []
values_for_avg = []
for entry in data:
# Convert timestamp to Unix time for comparison
timestamp = datetime.strptime(entry["timestamp"], '%Y-%m-%d %H:%M:%S').timestamp()
if pre_violation_start <= timestamp < pre_violation_end: # Filter within pre-violation window
filtered_data.append(entry)
values_for_avg.append(float(entry[f"{query_type}_value"]))
# Calculate the average of the filtered values
avg_value = sum(values_for_avg) / len(values_for_avg) if values_for_avg else 0.0
# Add average value to the result as a summary field
summary = {
"summary": {
"timestamp": detected_violation_timestamp,
f"{query_type}_avg_before_violation": avg_value
}
}
filtered_data.append(summary)
# Save the filtered pre-violation data
with open(output_file, 'w') as json_file:
json.dump(filtered_data, json_file, indent=4)
print(f"Filtered and averaged pre-violation data for {query_type} has been saved to {output_file}")
logging.info(f"Filtered and averaged pre-violation data for {query_type} has been saved to {output_file}")
# Call the function for inbyte and outbyte
filter_previolation_octets('monitor_filtered_ifinbytes.json', 'monitor_before_violation_ifinbytes.json',
'inbyte')
filter_previolation_octets('monitor_filtered_ifoutbytes.json', 'monitor_before_violation_ifoutbytes.json',
'outbyte')
#>>>>> here to get the average for the previolation data
# New calculate_ifname_avg function
def calculate_ifname_avg(input_file, output_file, query_type):
"""
Calculates the average of values grouped by 'ifname' from the input JSON file.
"""
# New function code here
with open(input_file, 'r') as file:
data = json.load(file)
# Dictionary to store totals and counts
ifname_data = defaultdict(lambda: {'total': 0, 'count': 0})
for entry in data:
if "ifname" in entry and f"{query_type}_value" in entry:
ifname = entry["ifname"]
value = float(entry[f"{query_type}_value"])
ifname_data[ifname]['total'] += value
ifname_data[ifname]['count'] += 1
# Calculate averages and save to output
result = []
for ifname, stats in ifname_data.items():
avg_value = stats['total'] / stats['count'] if stats['count'] > 0 else 0
result.append({
"ifname": ifname,
f"{query_type}_avg_before_violation": avg_value
})
with open(output_file, 'w') as file:
json.dump(result, file, indent=4)
print(f"Averages grouped by 'ifname' saved to {output_file}")
# Call the new function to generate average files
calculate_ifname_avg('monitor_before_violation_ifinbytes.json', 'monitor_avg_before_violation_ifinbytes.json',
'inbyte')
calculate_ifname_avg('monitor_before_violation_ifoutbytes.json', 'monitor_avg_before_violation_ifoutbytes.json',
'outbyte')
#>>>>>> calculate violation data here
def filter_violation_octets(filtered_file, output_file, query_type):
"""
Filters data within the violation window (violation timestamp to 5 minutes after)
and calculates average values.
"""
global detected_violation_timestamp
if detected_violation_timestamp is None:
print("No violation detected. Skipping violation data collection for octets.")
logging.info("No violation detected. Skipping violation data collection for octets.")
return
# Convert detected_violation_timestamp to Unix time
violation_timestamp = int(datetime.strptime(detected_violation_timestamp, '%Y-%m-%d %H:%M:%S').timestamp())
# Define start and end of the violation window (violation + 5 minutes = 300 seconds)
violation_start = violation_timestamp
violation_end = violation_timestamp + 300 # 5 minutes after violation
# Load the filtered octet data
with open(filtered_file, 'r') as json_file:
data = json.load(json_file)
# Filter data based on the violation window
filtered_data = []
values_for_avg = []
for entry in data:
# Convert timestamp to Unix time for comparison
timestamp = datetime.strptime(entry["timestamp"], '%Y-%m-%d %H:%M:%S').timestamp()
if violation_start <= timestamp < violation_end: # Filter within violation window
filtered_data.append(entry)
values_for_avg.append(float(entry[f"{query_type}_value"]))
# Calculate the average of the filtered values
avg_value = sum(values_for_avg) / len(values_for_avg) if values_for_avg else 0.0
# Add average value to the result as a summary field
summary = {
"summary": {
"timestamp": detected_violation_timestamp,
f"{query_type}_avg_violation": avg_value