serverwatcher 5.30.8__tar.gz → 5.31__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {serverwatcher-5.30.8/src/serverwatcher.egg-info → serverwatcher-5.31}/PKG-INFO +1 -1
- {serverwatcher-5.30.8 → serverwatcher-5.31}/pyproject.toml +1 -1
- {serverwatcher-5.30.8 → serverwatcher-5.31}/src/serverwatcher/__main__.py +8 -8
- {serverwatcher-5.30.8 → serverwatcher-5.31}/src/serverwatcher/configclasses/config.py +17 -13
- {serverwatcher-5.30.8 → serverwatcher-5.31}/src/serverwatcher/configclasses/watcher.py +26 -26
- {serverwatcher-5.30.8 → serverwatcher-5.31}/src/serverwatcher/defaultconfigs/config.yaml +5 -3
- {serverwatcher-5.30.8 → serverwatcher-5.31}/src/serverwatcher/defaultconfigs/messages.yaml +1 -1
- {serverwatcher-5.30.8 → serverwatcher-5.31}/src/serverwatcher/validator.py +3 -3
- {serverwatcher-5.30.8 → serverwatcher-5.31}/src/serverwatcher/watcher.py +16 -11
- {serverwatcher-5.30.8 → serverwatcher-5.31/src/serverwatcher.egg-info}/PKG-INFO +1 -1
- {serverwatcher-5.30.8 → serverwatcher-5.31}/LICENSE +0 -0
- {serverwatcher-5.30.8 → serverwatcher-5.31}/README.md +0 -0
- {serverwatcher-5.30.8 → serverwatcher-5.31}/setup.cfg +0 -0
- {serverwatcher-5.30.8 → serverwatcher-5.31}/src/serverwatcher/__init__.py +0 -0
- {serverwatcher-5.30.8 → serverwatcher-5.31}/src/serverwatcher/configclasses/__init__.py +0 -0
- {serverwatcher-5.30.8 → serverwatcher-5.31}/src/serverwatcher/configclasses/messages.py +0 -0
- {serverwatcher-5.30.8 → serverwatcher-5.31}/src/serverwatcher/defaultconfigs/watcher.yaml +0 -0
- {serverwatcher-5.30.8 → serverwatcher-5.31}/src/serverwatcher.egg-info/SOURCES.txt +0 -0
- {serverwatcher-5.30.8 → serverwatcher-5.31}/src/serverwatcher.egg-info/dependency_links.txt +0 -0
- {serverwatcher-5.30.8 → serverwatcher-5.31}/src/serverwatcher.egg-info/requires.txt +0 -0
- {serverwatcher-5.30.8 → serverwatcher-5.31}/src/serverwatcher.egg-info/top_level.txt +0 -0
|
@@ -14,34 +14,34 @@ def main():
|
|
|
14
14
|
validate_all()
|
|
15
15
|
|
|
16
16
|
except FatalError as e:
|
|
17
|
-
print(
|
|
17
|
+
print('❌ FATAL CONFIG ERROR:')
|
|
18
18
|
print(e)
|
|
19
19
|
return
|
|
20
20
|
|
|
21
21
|
except TypeMismatchError as e:
|
|
22
|
-
print(
|
|
22
|
+
print('❌ TYPE MISMATCH ERROR:')
|
|
23
23
|
print(e)
|
|
24
24
|
return
|
|
25
25
|
|
|
26
26
|
except FallbackError as e:
|
|
27
|
-
print(
|
|
27
|
+
print('⚠️ FALLBACKS IN USE:')
|
|
28
28
|
print(e)
|
|
29
|
-
print(
|
|
29
|
+
print('Continuing in 5 seconds...')
|
|
30
30
|
time.sleep(5)
|
|
31
31
|
|
|
32
32
|
except RecommendedError as e:
|
|
33
|
-
print(
|
|
33
|
+
print('⚠️ RECOMMENDED KEYS MISSING:')
|
|
34
34
|
print(e)
|
|
35
|
-
print(
|
|
35
|
+
print('Continuing in 5 seconds...')
|
|
36
36
|
time.sleep(5)
|
|
37
37
|
|
|
38
38
|
except ValidationError as e:
|
|
39
|
-
print(
|
|
39
|
+
print('❌ CONFIG ERROR:')
|
|
40
40
|
print(e)
|
|
41
41
|
return
|
|
42
42
|
|
|
43
43
|
watcher = ServerWatcher()
|
|
44
44
|
watcher.run()
|
|
45
45
|
|
|
46
|
-
if __name__ ==
|
|
46
|
+
if __name__ == '__main__':
|
|
47
47
|
main()
|
|
@@ -5,6 +5,7 @@ class GlobalConfig:
|
|
|
5
5
|
__user_config_path__ = 'config/config.yaml'
|
|
6
6
|
__default_config_path__ = 'defaultconfigs/config.yaml'
|
|
7
7
|
|
|
8
|
+
debug: bool = 'debug'
|
|
8
9
|
timezone: str = 'timezone'
|
|
9
10
|
|
|
10
11
|
panel_name: str = 'panel.name'
|
|
@@ -26,12 +27,14 @@ class GlobalConfig:
|
|
|
26
27
|
info_prefix: str = 'logger.prefixes.info'
|
|
27
28
|
warn_prefix: str = 'logger.prefixes.warn'
|
|
28
29
|
error_prefix: str = 'logger.prefixes.error'
|
|
30
|
+
debug_prefix: str = 'logger.prefixes.debug'
|
|
29
31
|
|
|
30
32
|
clear_terminal: bool = 'terminal.enable_clearing'
|
|
31
33
|
handle_keyboard_interrupt: bool = 'terminal.handle_keyboard_interrupt'
|
|
32
34
|
|
|
33
35
|
|
|
34
36
|
class fallbacks:
|
|
37
|
+
debug = False
|
|
35
38
|
timezone = 'America/Chicago'
|
|
36
39
|
|
|
37
40
|
panel_name = 'My Panel'
|
|
@@ -50,24 +53,25 @@ class fallbacks:
|
|
|
50
53
|
logger_name = 'Server Watcher'
|
|
51
54
|
log_path = '/home/container/logs/'
|
|
52
55
|
|
|
53
|
-
info_prefix = '<white>[INFO]: '
|
|
54
|
-
warn_prefix = '<yellow>[WARN]: '
|
|
55
|
-
error_prefix = '<red>[ERROR]: '
|
|
56
|
+
info_prefix = '<white>[%hh%:%mm%:%ss%] [INFO]: '
|
|
57
|
+
warn_prefix = '<yellow>[%hh%:%mm%:%ss%] [WARN]: '
|
|
58
|
+
error_prefix = '<red>[%hh%:%mm%:%ss%] [ERROR]: '
|
|
59
|
+
debug_prefix = '<aqua>[%hh%:%mm%:%ss%] [DEBUG]: '
|
|
56
60
|
|
|
57
61
|
clear_terminal = True
|
|
58
62
|
handle_keyboard_interrupt = True
|
|
59
63
|
|
|
60
64
|
|
|
61
65
|
class rules:
|
|
62
|
-
panel_url =
|
|
63
|
-
panel_api_key =
|
|
64
|
-
server_id =
|
|
65
|
-
server_domain =
|
|
66
|
-
bridge_token =
|
|
67
|
-
|
|
68
|
-
timezone =
|
|
69
|
-
panel_name =
|
|
70
|
-
server_port =
|
|
71
|
-
bridge_port =
|
|
66
|
+
panel_url = 'required'
|
|
67
|
+
panel_api_key = 'required'
|
|
68
|
+
server_id = 'required'
|
|
69
|
+
server_domain = 'required'
|
|
70
|
+
bridge_token = 'required'
|
|
71
|
+
|
|
72
|
+
timezone = 'recommended'
|
|
73
|
+
panel_name = 'recommended'
|
|
74
|
+
server_port = 'recommended'
|
|
75
|
+
bridge_port = 'recommended'
|
|
72
76
|
|
|
73
77
|
# everything else defaults to optional
|
|
@@ -71,29 +71,29 @@ class fallbacks:
|
|
|
71
71
|
|
|
72
72
|
|
|
73
73
|
class rules:
|
|
74
|
-
threshold_ram =
|
|
75
|
-
threshold_cpu =
|
|
76
|
-
threshold_uptime =
|
|
77
|
-
threshold_tps =
|
|
78
|
-
|
|
79
|
-
restart_wait_seconds =
|
|
80
|
-
restart_timeout =
|
|
81
|
-
restart_online_interval =
|
|
82
|
-
|
|
83
|
-
watch_interval =
|
|
84
|
-
sample_duration =
|
|
85
|
-
sample_interval =
|
|
86
|
-
sample_outlier_drop =
|
|
87
|
-
threshold_min_uptime =
|
|
88
|
-
threshold_low_gap =
|
|
89
|
-
snap_minutes =
|
|
90
|
-
low_gap_minutes =
|
|
91
|
-
high_gap_minutes =
|
|
92
|
-
|
|
93
|
-
weight_restart_soon =
|
|
94
|
-
weight_ram =
|
|
95
|
-
weight_cpu =
|
|
96
|
-
weight_uptime =
|
|
97
|
-
weight_tps =
|
|
98
|
-
weight_low_uptime =
|
|
99
|
-
weight_per_player =
|
|
74
|
+
threshold_ram = 'required'
|
|
75
|
+
threshold_cpu = 'required'
|
|
76
|
+
threshold_uptime = 'required'
|
|
77
|
+
threshold_tps = 'required'
|
|
78
|
+
|
|
79
|
+
restart_wait_seconds = 'required'
|
|
80
|
+
restart_timeout = 'required'
|
|
81
|
+
restart_online_interval = 'required'
|
|
82
|
+
|
|
83
|
+
watch_interval = 'recommended'
|
|
84
|
+
sample_duration = 'recommended'
|
|
85
|
+
sample_interval = 'recommended'
|
|
86
|
+
sample_outlier_drop = 'recommended'
|
|
87
|
+
threshold_min_uptime = 'recommended'
|
|
88
|
+
threshold_low_gap = 'recommended'
|
|
89
|
+
snap_minutes = 'recommended'
|
|
90
|
+
low_gap_minutes = 'recommended'
|
|
91
|
+
high_gap_minutes = 'recommended'
|
|
92
|
+
|
|
93
|
+
weight_restart_soon = 'optional'
|
|
94
|
+
weight_ram = 'optional'
|
|
95
|
+
weight_cpu = 'optional'
|
|
96
|
+
weight_uptime = 'optional'
|
|
97
|
+
weight_tps = 'optional'
|
|
98
|
+
weight_low_uptime = 'optional'
|
|
99
|
+
weight_per_player = 'optional'
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
debug: False
|
|
1
2
|
timezone: 'America/Chicago'
|
|
2
3
|
|
|
3
4
|
panel:
|
|
@@ -21,9 +22,10 @@ logger:
|
|
|
21
22
|
log_path: '/home/container/logs/'
|
|
22
23
|
|
|
23
24
|
prefixes:
|
|
24
|
-
info:
|
|
25
|
-
warn:
|
|
26
|
-
error:
|
|
25
|
+
info: '<white>[%hh%:%mm%:%ss%] [INFO]: '
|
|
26
|
+
warn: '<yellow>[%hh%:%mm%:%ss%] [WARN]: '
|
|
27
|
+
error: '<red>[%hh%:%mm%:%ss%] [ERROR]: '
|
|
28
|
+
debug: '<aqua>[%hh%:%mm%:%ss%] [DEBUG]: '
|
|
27
29
|
|
|
28
30
|
terminal:
|
|
29
31
|
enable_clearing: True
|
|
@@ -73,7 +73,7 @@ reasons:
|
|
|
73
73
|
uptime: 'Uptime {uptime} exceeds {threshold}h'
|
|
74
74
|
tps: 'TPS {tps} is lower than {threshold}'
|
|
75
75
|
low_uptime: 'Uptime {uptime} is shorter than 30m'
|
|
76
|
-
players: 'There {verb} {count} {plural} online' # produces:
|
|
76
|
+
players: 'There {verb} {count} {plural} online' # produces: 'There are 2 players online' or 'There is 1 player online'
|
|
77
77
|
|
|
78
78
|
pro_restart_number: 'Pro-restart: '
|
|
79
79
|
anti_restart_number: 'Anti-restart:'
|
|
@@ -15,19 +15,19 @@ v = Validator()
|
|
|
15
15
|
|
|
16
16
|
def validate_global_config(c):
|
|
17
17
|
for f in fields(GlobalConfig):
|
|
18
|
-
if not f.name.startswith(
|
|
18
|
+
if not f.name.startswith('__'):
|
|
19
19
|
v.check_field(c, f.name)
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
def validate_watcher_config(c):
|
|
23
23
|
for f in fields(WatcherConfig):
|
|
24
|
-
if not f.name.startswith(
|
|
24
|
+
if not f.name.startswith('__'):
|
|
25
25
|
v.check_field(c, f.name)
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
def validate_messages_config(c):
|
|
29
29
|
for f in fields(MessagesConfig):
|
|
30
|
-
if not f.name.startswith(
|
|
30
|
+
if not f.name.startswith('__'):
|
|
31
31
|
v.check_field(c, f.name)
|
|
32
32
|
|
|
33
33
|
|
|
@@ -124,10 +124,10 @@ class ServerWatcher:
|
|
|
124
124
|
minimumMinutes=minutes,
|
|
125
125
|
snapMinutes=tuple(sorted(self.watcherconfig.snap_minutes))
|
|
126
126
|
)
|
|
127
|
-
scheduled = info[
|
|
127
|
+
scheduled = info['scheduled']
|
|
128
128
|
|
|
129
129
|
local_time = scheduled.astimezone(self.tz)
|
|
130
|
-
time_str = local_time.strftime(
|
|
130
|
+
time_str = local_time.strftime('%I:%M %p')
|
|
131
131
|
|
|
132
132
|
self.router.broadcast(self.messages.broadcast_restart_at, time=time_str)
|
|
133
133
|
|
|
@@ -169,7 +169,7 @@ class ServerWatcher:
|
|
|
169
169
|
)
|
|
170
170
|
|
|
171
171
|
def evaluate(self):
|
|
172
|
-
self.router.info(
|
|
172
|
+
self.router.info('ServerWatcher is running!')
|
|
173
173
|
utils.clearTerminal()
|
|
174
174
|
|
|
175
175
|
self.router.info(self.messages.startup)
|
|
@@ -193,6 +193,13 @@ class ServerWatcher:
|
|
|
193
193
|
restart_reasons = []
|
|
194
194
|
no_restart_reasons = []
|
|
195
195
|
|
|
196
|
+
if self.config.debug:
|
|
197
|
+
self.router.origin(f'RAM: {snap.ram}/{self.watcherconfig.threshold_ram}', level=self.config.debug_prefix)
|
|
198
|
+
self.router.origin(f'CPU: {snap.cpu}/{self.watcherconfig.threshold_cpu}', level=self.config.debug_prefix)
|
|
199
|
+
self.router.origin(f'Uptime: {snap.uptime // 3600}/{self.watcherconfig.threshold_uptime}', level=self.config.debug_prefix)
|
|
200
|
+
self.router.origin(f'TPS: {snap.tps}/{self.watcherconfig.threshold_tps}', level=self.config.debug_prefix)
|
|
201
|
+
self.router.origin(f'Players: {snap.players}', level=self.config.debug_prefix)
|
|
202
|
+
|
|
196
203
|
if snap.ram >= self.watcherconfig.threshold_ram:
|
|
197
204
|
restart_reasons.append(self.res(self.messages.reason_ram, ram=snap.ram, threshold=self.watcherconfig.threshold_ram))
|
|
198
205
|
pro += int(round(snap.ram, 0) - (self.watcherconfig.threshold_ram - 1))
|
|
@@ -214,23 +221,23 @@ class ServerWatcher:
|
|
|
214
221
|
anti += self.watcherconfig.weight_low_uptime
|
|
215
222
|
|
|
216
223
|
if snap.players > 0:
|
|
217
|
-
verb =
|
|
218
|
-
plural =
|
|
224
|
+
verb = 'are' if snap.players != 1 else 'is'
|
|
225
|
+
plural = 'players' if snap.players != 1 else 'player'
|
|
219
226
|
no_restart_reasons.append(self.res(self.messages.reason_players, verb=verb, count=snap.players, plural=plural))
|
|
220
227
|
anti += snap.players * self.watcherconfig.weight_per_player
|
|
221
228
|
|
|
222
229
|
if restart_reasons:
|
|
223
230
|
self.router.warn(self.messages.pro_restart_splash)
|
|
224
231
|
for r in restart_reasons:
|
|
225
|
-
self.router.warn(f
|
|
232
|
+
self.router.warn(f'{self.messages.bullet} {r}')
|
|
226
233
|
|
|
227
234
|
if no_restart_reasons:
|
|
228
235
|
self.router.warn(self.messages.anti_restart_splash)
|
|
229
236
|
for r in no_restart_reasons:
|
|
230
|
-
self.router.warn(f
|
|
237
|
+
self.router.warn(f'{self.messages.bullet} {r}')
|
|
231
238
|
|
|
232
|
-
self.router.warn(f
|
|
233
|
-
self.router.warn(f
|
|
239
|
+
self.router.warn(f'{self.messages.pro_restart_number} {pro}')
|
|
240
|
+
self.router.warn(f'{self.messages.anti_restart_number} {anti}')
|
|
234
241
|
|
|
235
242
|
gap = abs(pro - anti)
|
|
236
243
|
|
|
@@ -259,13 +266,11 @@ class ServerWatcher:
|
|
|
259
266
|
if self.config.handle_keyboard_interrupt:
|
|
260
267
|
try:
|
|
261
268
|
while True:
|
|
262
|
-
self.clearTerminal()
|
|
263
269
|
self.evaluate()
|
|
264
270
|
time.sleep(self.watcherconfig.watch_interval)
|
|
265
271
|
except KeyboardInterrupt:
|
|
266
272
|
self.shutdown()
|
|
267
273
|
else:
|
|
268
274
|
while True:
|
|
269
|
-
self.clearTerminal()
|
|
270
275
|
self.evaluate()
|
|
271
276
|
time.sleep(self.watcherconfig.watch_interval)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|