dbworkload 0.8.2__tar.gz → 0.8.4__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.
- {dbworkload-0.8.2 → dbworkload-0.8.4}/PKG-INFO +1 -1
- {dbworkload-0.8.2 → dbworkload-0.8.4}/dbworkload/models/run.py +45 -29
- {dbworkload-0.8.2 → dbworkload-0.8.4}/pyproject.toml +1 -1
- {dbworkload-0.8.2 → dbworkload-0.8.4}/LICENSE +0 -0
- {dbworkload-0.8.2 → dbworkload-0.8.4}/README.md +0 -0
- {dbworkload-0.8.2 → dbworkload-0.8.4}/dbworkload/__init__.py +0 -0
- {dbworkload-0.8.2 → dbworkload-0.8.4}/dbworkload/cli/dep.py +0 -0
- {dbworkload-0.8.2 → dbworkload-0.8.4}/dbworkload/cli/main.py +0 -0
- {dbworkload-0.8.2 → dbworkload-0.8.4}/dbworkload/cli/util.py +0 -0
- {dbworkload-0.8.2 → dbworkload-0.8.4}/dbworkload/models/util.py +0 -0
- {dbworkload-0.8.2 → dbworkload-0.8.4}/dbworkload/templates/stub.j2 +0 -0
- {dbworkload-0.8.2 → dbworkload-0.8.4}/dbworkload/utils/common.py +0 -0
- {dbworkload-0.8.2 → dbworkload-0.8.4}/dbworkload/utils/simplefaker.py +0 -0
|
@@ -15,6 +15,7 @@ from threading import Thread
|
|
|
15
15
|
|
|
16
16
|
import numpy as np
|
|
17
17
|
import tabulate
|
|
18
|
+
from psutil import cpu_percent, virtual_memory
|
|
18
19
|
|
|
19
20
|
import dbworkload.utils.common
|
|
20
21
|
from dbworkload.cli.dep import ConnInfo
|
|
@@ -31,11 +32,13 @@ from dbworkload.cli.dep import ConnInfo
|
|
|
31
32
|
DEFAULT_SLEEP = 3
|
|
32
33
|
MAX_RETRIES = 3
|
|
33
34
|
FREQUENCY = 10
|
|
35
|
+
STATS_BUFFER = 8
|
|
34
36
|
|
|
35
37
|
FIFO = "dbworkload.pipe"
|
|
36
38
|
|
|
37
39
|
logger = logging.getLogger("dbworkload")
|
|
38
40
|
|
|
41
|
+
force_exit = False
|
|
39
42
|
|
|
40
43
|
HEADERS: list = [
|
|
41
44
|
"elapsed",
|
|
@@ -95,6 +98,12 @@ def signal_handler(sig, frame):
|
|
|
95
98
|
frame (_type_):
|
|
96
99
|
"""
|
|
97
100
|
logger.info("KeyboardInterrupt signal detected. Stopping processes...")
|
|
101
|
+
global force_exit
|
|
102
|
+
if force_exit:
|
|
103
|
+
logger.warning("Forcibly quitting. You're rude!")
|
|
104
|
+
sys.exit(1)
|
|
105
|
+
|
|
106
|
+
force_exit = True
|
|
98
107
|
|
|
99
108
|
# send the poison pill to each proc.
|
|
100
109
|
# if dbworkload cannot graceful shutdown due
|
|
@@ -104,13 +113,15 @@ def signal_handler(sig, frame):
|
|
|
104
113
|
# and raise the queue.Full exception, forcing to quit.
|
|
105
114
|
for q in queues.values():
|
|
106
115
|
try:
|
|
107
|
-
q.put("proc_end"
|
|
116
|
+
q.put("proc_end")
|
|
108
117
|
except queue.Full:
|
|
109
118
|
logger.error("Timed out")
|
|
110
119
|
sys.exit(1)
|
|
111
120
|
|
|
112
121
|
logger.debug("Sent poison pill to all procs")
|
|
113
|
-
|
|
122
|
+
|
|
123
|
+
if os.path.exists(FIFO):
|
|
124
|
+
os.remove(FIFO)
|
|
114
125
|
|
|
115
126
|
|
|
116
127
|
def cycle(iterable, backwards=False):
|
|
@@ -181,18 +192,15 @@ def run(
|
|
|
181
192
|
log_level: str,
|
|
182
193
|
):
|
|
183
194
|
def gracefully_shutdown(by_keyinterrupt: bool = False):
|
|
184
|
-
""
|
|
185
|
-
wait for final stat reports to come in,
|
|
186
|
-
then print final stats and quit
|
|
187
|
-
"""
|
|
195
|
+
logger.debug("Gracefully shutting down...")
|
|
188
196
|
|
|
189
197
|
end_time = int(time.time())
|
|
190
|
-
_s = stats_received
|
|
198
|
+
# _s = stats_received
|
|
191
199
|
|
|
192
200
|
if not by_keyinterrupt:
|
|
193
201
|
for q in queues.values():
|
|
194
202
|
try:
|
|
195
|
-
q.put("proc_end"
|
|
203
|
+
q.put("proc_end")
|
|
196
204
|
except queue.Full:
|
|
197
205
|
logger.error("Timed out")
|
|
198
206
|
sys.exit(1)
|
|
@@ -201,20 +209,23 @@ def run(
|
|
|
201
209
|
if x.is_alive():
|
|
202
210
|
x.join()
|
|
203
211
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
212
|
+
# Commenting the below as in theory there shouldn't be any stats that
|
|
213
|
+
# comes in *after* the PROC returns. That is, all threads send stats
|
|
214
|
+
# when all threads are returned, then the supervisor returns.
|
|
215
|
+
# while True:
|
|
216
|
+
# try:
|
|
217
|
+
# msg = to_main_q.get(block=True, timeout=2.0)
|
|
218
|
+
# if isinstance(msg, list):
|
|
219
|
+
# _s += 1
|
|
220
|
+
# stats.add_tds(msg)
|
|
221
|
+
# if _s >= active_connections:
|
|
222
|
+
# break
|
|
223
|
+
# else:
|
|
224
|
+
# logger.error("Timed out, quitting")
|
|
225
|
+
# sys.exit(1)
|
|
226
|
+
|
|
227
|
+
# except queue.Empty:
|
|
228
|
+
# break
|
|
218
229
|
|
|
219
230
|
# now that we have all stat reports, calculate the stats one last time.
|
|
220
231
|
report = stats.calculate_stats(active_connections, end_time)
|
|
@@ -374,10 +385,10 @@ def run(
|
|
|
374
385
|
)
|
|
375
386
|
supervisors[x].start()
|
|
376
387
|
|
|
377
|
-
# report time happens
|
|
388
|
+
# report time happens STATS_BUFFER seconds after the stats are received.
|
|
378
389
|
# we add this buffer to make sure we get all the stats reports
|
|
379
390
|
# from each thread before we aggregate and display
|
|
380
|
-
report_time = start_time + FREQUENCY +
|
|
391
|
+
report_time = start_time + FREQUENCY + STATS_BUFFER
|
|
381
392
|
|
|
382
393
|
returned_procs = 0
|
|
383
394
|
active_connections = 0
|
|
@@ -478,6 +489,7 @@ def run(
|
|
|
478
489
|
active_connections -= 1
|
|
479
490
|
elif msg == "proc_returned":
|
|
480
491
|
returned_procs += 1
|
|
492
|
+
logger.debug(f"Stopped processes: {returned_procs}/{procs} ")
|
|
481
493
|
elif msg == "task_done":
|
|
482
494
|
returned_threads += 1
|
|
483
495
|
except queue.Empty:
|
|
@@ -501,11 +513,15 @@ def run(
|
|
|
501
513
|
sys.exit(1)
|
|
502
514
|
|
|
503
515
|
if time.time() >= report_time:
|
|
504
|
-
|
|
505
|
-
|
|
516
|
+
cpu_util = cpu_percent()
|
|
517
|
+
vmem = virtual_memory().percent
|
|
518
|
+
if stats_received != active_connections or cpu_util > 70 or vmem > 70:
|
|
519
|
+
logger.warning(
|
|
520
|
+
f"{stats_received=}, expected={active_connections}. CPU Util={cpu_util}%, Memory={vmem}%"
|
|
521
|
+
)
|
|
506
522
|
|
|
507
|
-
# remove the
|
|
508
|
-
endtime = int(time.time()) -
|
|
523
|
+
# remove the STATS_BUFFER seconds added
|
|
524
|
+
endtime = int(time.time()) - STATS_BUFFER
|
|
509
525
|
|
|
510
526
|
report = stats.calculate_stats(active_connections, endtime)
|
|
511
527
|
|
|
@@ -580,7 +596,7 @@ def run(
|
|
|
580
596
|
report_time += FREQUENCY
|
|
581
597
|
|
|
582
598
|
# pause briefly to prevent the loop from overheating the CPU
|
|
583
|
-
time.sleep(0.
|
|
599
|
+
time.sleep(0.001)
|
|
584
600
|
|
|
585
601
|
gracefully_shutdown()
|
|
586
602
|
|
|
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
|