-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlog_time.py
More file actions
225 lines (199 loc) · 7.79 KB
/
log_time.py
File metadata and controls
225 lines (199 loc) · 7.79 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
import asyncio
import json
import logging
import sys
from datetime import datetime, timedelta
from inspect import signature
import requests
import urllib3
import yaml
from sqlalchemy import Column, DateTime, Integer, MetaData, String, Table, create_engine
from sqlalchemy.sql.sqltypes import Boolean
urllib3.disable_warnings() # disabling warings about lacking of HTTPS
# Load config file
with open("example_config.yml", mode="r") as file:
config = yaml.full_load(file)
# Logining configuration
logging.basicConfig(
filename=config["logs"]["filename"],
filemode=config["logs"]["filemode"],
level=logging.INFO,
format="%(asctime)s - %(levelname)s - %(message)s",
datefmt="%m/%d/%Y %I:%M:%S",
)
##RocketChat WeebHook and headers##
url = config["credentials"]["ROCKETCHAT"]["webhook"]
headers: dict = config["credentials"]["ROCKETCHAT"]["headers"]
# SQL engine and table maping
engine = create_engine(
config["credentials"]["DB"]["engine"]
+ "://"
+ config["credentials"]["DB"]["username"]
+ ":"
+ config["credentials"]["DB"]["password"]
+ "@"
+ config["credentials"]["DB"]["adress"]
+ "/"
+ config["credentials"]["DB"]["db"]
)
metadata = MetaData()
hearthbeat = Table(
config["credentials"]["DB"]["table"],
metadata,
Column("server", String(10)),
Column("date_time", DateTime),
Column("time_diff", String(30)),
Column("seconds_diff", Integer),
)
class OvRunCheck(object):
def __init__(
self,
name: str,
adress: str,
format: str = "%Y-%m-%d %H:%M:%S",
last_run: str = "1920-01-01T00:00:00.000+02:00",
db_save: bool = True,
notification: bool = True,
msg_interval: int = 5,
notification_treshold: int = 15,
) -> None:
"""
Timer class used to check content of remote adress
:param name(str): name of server
:param adress(str): HTTP/HTTPS adress used in GET request
:param format(str): Default: 'YYYY-MM-DD HH:MM:SS' Format used in .strftime to diplay current time in human form.
:param last_run(str): Default: '1920-01-01 00:00:00' DateTime from which diff will be calulated.
:param db_save(bool): Define if changes in computed time should be looged to DB. (Default: True)
:param notification(bool): Define if notification should be send via RocketChat. (Default: True)
:param msg_interval(int): Specify how often notification should be send via RocketChat. (Default: 5min)
:param notification_treshold(int): Specify time period after which first notfication will be send (Default: 15min).
"""
self.name = name
self.adress = adress
self.format = format
self.last_run = datetime.fromisoformat(last_run)
self.db_save = db_save
self.notification = notification
self.msg_interval = msg_interval
self.notification_treshold = notification_treshold
self.inc = notification_treshold
def __str__(self) -> str:
fields = signature(self.__init__).parameters
values = ", ".join(str(getattr(self, f)) for f in fields)
return f"""{self.name}({values})"""
def __repr__(self) -> str:
return str(self.__dict__)
@property
def current_time(self):
try:
# Ignoring SSL as we do not send reacive anything sensitive
response = requests.get(self.adress, verify=False).json()
except requests.exceptions.RequestException:
logging.error(f"{self.name} - SSLError {sys.exc_info()[0]}")
response = None
if response:
current_time = datetime.fromisoformat(
response["data_version"]["computed_refresh_date"]
)
else:
current_time = datetime.fromisoformat("9999-12-12T00:00:00.000+00:00")
return current_time
@property
def now(self):
try:
# Ignoring SSL as we do not send reacive anything sensitive
response = requests.get(self.adress, verify=False).json()
except requests.exceptions.RequestException:
logging.error(f"{self.name} - SSLError {sys.exc_info()[0]}")
response = None
if response:
now = datetime.fromisoformat(response["data_version"]["now"])
else:
now = datetime.fromisoformat("8999-12-12T00:00:00.000+00:00")
return now
def show_time(self) -> str:
string_time = self.current_time.strftime(self.format)
print(string_time)
def time_diff(self):
if self.last_run < self.current_time:
try:
diff = self.current_time - self.last_run
if self.db_save == True:
ins = hearthbeat.insert().values(
server=self.name,
date_time=self.now,
time_diff=str(diff),
seconds_diff=diff.total_seconds(),
)
try:
conn = engine.connect()
insert = conn.execute(ins)
insert.close()
except:
errmsg = f"{self.name} - Error during save to Database {sys.exc_info()[0]}"
logging.error(errmsg)
print(errmsg)
msg = f"{self.name} - OV run detected, previous run lasted {str(diff)}"
logging.info(msg)
print(msg)
self.last_run = self.current_time
self.inc = self.msg_interval
except:
errmsg = f"{self.name} - Unknow error {sys.exc_info()[0]}"
logging.error(errmsg)
print(errmsg)
# Exeption need to be replace with more specific, currently don't know what can happen here
else:
# This should be split into smaller method/fuction with more specific exeptions.
# I know it work but it is horrible
diff = self.now - self.last_run
if (
diff > timedelta(minutes=self.notification_treshold)
and self.notification == True
and self.inc % self.msg_interval == 0
):
try:
requests.post(
url,
data=json.dumps(
{
"text": f"**{self.name}** - Ostatni przebieg OV {str(diff)} temu"
}
),
headers=headers,
)
except:
errmsg = f"{self.name} - Error during sending notification {sys.exc_info()[0]}"
logging.error(errmsg)
print(errmsg)
msg = f"{self.name} - No run occured, waiting 60s"
logging.info(msg)
print(msg)
self.inc += 1
serverlist: list = []
print("Application starting")
for key in config["servers"]:
serverlist.append(
OvRunCheck(
name=config["servers"][key]["name"],
adress=config["servers"][key]["adress"],
db_save=config["servers"][key]["db_save"],
notification=config["servers"][key]["notification"],
msg_interval=config["servers"][key]["msg_interval"],
notification_treshold=config["servers"][key]["notification_treshold"],
)
)
print("Loaded objects:")
for server in serverlist:
print(server)
loop = asyncio.get_event_loop()
async def while_loop():
while True:
start = datetime.now()
for server in serverlist:
server.time_diff()
end = datetime.now()
elaps = end - start
await asyncio.sleep(config["main"]["checkup_interval"] - elaps.total_seconds())
loop.create_task(while_loop())
loop.run_forever()