-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathServer.py
More file actions
133 lines (111 loc) · 3.93 KB
/
Copy pathServer.py
File metadata and controls
133 lines (111 loc) · 3.93 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
import datetime
import json
import socket
import threading
import time
from abc import ABC, abstractmethod
from prometheus_client import start_http_server, Summary, Gauge, Counter, Histogram
HOST = '127.0.0.1'
PORT = 8686
# Defalut metrics
# CPU count
cpu_count = Gauge('cpu_count', 'CPU count', ['agent_name'])
# CPU usage
cpu_usage = Gauge('cpu_usage', 'CPU usage', ['agent_name'])
# memory usage
memory_usage = Gauge('memory_usage', 'Memory usage', ['agent_name'])
# disk usage
disk_usage = Gauge('disk_usage', 'Disk usage', ['agent_name'])
class Client:
"""
Class for storing client data including name, data type, prometheus_client object, conn
"""
def __init__(self, conn, addr):
self.conn = conn
self.addr = addr
def handel_received_data(self, data):
"""
Handel received data
:param data: data to be handeled
:return: void
"""
raw_data = data['data']
agent_name = data['name']
hostname = raw_data['hostname']
cpu_count.labels(f"{agent_name}:{hostname}").set(raw_data['cpu_count'])
cpu_usage.labels(f"{agent_name}:{hostname}").set(raw_data['cpu_percent'])
memory_usage.labels(f"{agent_name}:{hostname}").set(raw_data['memory_percent'])
disk_usage.labels(f"{agent_name}:{hostname}").set(raw_data['disk_percent'])
class Server:
"""
Class for server receiving data from agents
"""
socket = None
# list of clients connected to server
clients = []
def __init__(self):
self.name = "Server"
self.addr = None
self.conn = None
self.initial_socket()
def initial_socket(self):
"""
Initialize socket object
:return: Void
"""
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.bind((HOST, PORT))
def run_server(self):
"""
Run server as a service
:return: Void
"""
self.socket.listen(5)
while True:
# accept connection from client and create a thread for it
self.conn, self.addr = self.socket.accept()
# get initial data from client
initial_data = json.loads(self.conn.recv(1024).decode('utf-8'))
# create client object
client = Client(self.conn, self.addr)
# add client to list of clients
self.clients.append(client)
# log initial data
self.log(f"Received initial data from {self.addr}: {initial_data}")
self.log(f"Client {self.addr} connected")
threading.Thread(target=self.handle_client, args=(client,)).start()
def handle_client(self, client):
"""
Handle client connection
:param conn: client connection
:param addr: client address
:return: Void
"""
while True:
try:
data = client.conn.recv(1024)
except ConnectionResetError:
self.log(f"Client {client.addr} disconnected")
self.clients.remove(client)
break
if not data:
break
self.log(f"Received data from {client.addr}: {data.decode('utf-8')}")
client.handel_received_data(json.loads(data.decode('utf-8')))
def log(self, message, type='info'):
"""
Log given message with a specific format including system data and time
:param message: message to be logged
:param type: info, warning, error
"""
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
if type == 'info':
print(f"[INFO][{timestamp}] {self.name} : {message}")
elif type == 'warning':
print(f"[WARNING][{timestamp}] {self.name} : {message}")
elif type == 'error':
print(f"[ERROR][{timestamp}] {self.name} : {message}")
# Run server
start_http_server(8000)
server = Server()
server.run_server()