flowcept 0.8.2__py3-none-any.whl → 0.8.4__py3-none-any.whl
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.
- flowcept/commons/autoflush_buffer.py +4 -3
- flowcept/commons/daos/mq_dao/mq_dao_base.py +30 -22
- flowcept/commons/daos/mq_dao/mq_dao_kafka.py +19 -11
- flowcept/commons/daos/mq_dao/mq_dao_mofka.py +21 -8
- flowcept/commons/daos/mq_dao/mq_dao_redis.py +22 -11
- flowcept/configs.py +4 -4
- flowcept/flowceptor/adapters/dask/dask_interceptor.py +5 -28
- flowcept/flowceptor/adapters/dask/dask_plugins.py +20 -32
- flowcept/flowceptor/consumers/document_inserter.py +2 -2
- flowcept/version.py +1 -1
- {flowcept-0.8.2.dist-info → flowcept-0.8.4.dist-info}/METADATA +1 -1
- {flowcept-0.8.2.dist-info → flowcept-0.8.4.dist-info}/RECORD +15 -15
- resources/sample_settings.yaml +1 -0
- {flowcept-0.8.2.dist-info → flowcept-0.8.4.dist-info}/WHEEL +0 -0
- {flowcept-0.8.2.dist-info → flowcept-0.8.4.dist-info}/licenses/LICENSE +0 -0
|
@@ -9,13 +9,14 @@ class AutoflushBuffer:
|
|
|
9
9
|
|
|
10
10
|
def __init__(
|
|
11
11
|
self,
|
|
12
|
-
max_size,
|
|
13
|
-
flush_interval,
|
|
14
12
|
flush_function: Callable,
|
|
13
|
+
max_size=None,
|
|
14
|
+
flush_interval=None,
|
|
15
15
|
flush_function_args=[],
|
|
16
16
|
flush_function_kwargs={},
|
|
17
17
|
):
|
|
18
|
-
self._max_size = max_size
|
|
18
|
+
self._max_size = max_size or float("inf")
|
|
19
|
+
self._flush_interval = flush_interval or float("inf")
|
|
19
20
|
self._flush_interval = flush_interval
|
|
20
21
|
self._buffers = [[], []]
|
|
21
22
|
self._current_buffer_index = 0
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
"""MQ base module."""
|
|
2
2
|
|
|
3
|
-
import csv
|
|
4
3
|
from abc import ABC, abstractmethod
|
|
5
|
-
from time import time
|
|
6
4
|
from typing import Union, List, Callable
|
|
7
|
-
|
|
5
|
+
import csv
|
|
8
6
|
import msgpack
|
|
9
|
-
|
|
7
|
+
from time import time
|
|
10
8
|
import flowcept.commons
|
|
11
9
|
from flowcept.commons.autoflush_buffer import AutoflushBuffer
|
|
12
10
|
|
|
@@ -21,6 +19,7 @@ from flowcept.configs import (
|
|
|
21
19
|
MQ_INSERTION_BUFFER_TIME,
|
|
22
20
|
MQ_CHUNK_SIZE,
|
|
23
21
|
MQ_TYPE,
|
|
22
|
+
MQ_TIMING,
|
|
24
23
|
)
|
|
25
24
|
|
|
26
25
|
from flowcept.commons.utils import GenericJSONEncoder
|
|
@@ -71,12 +70,21 @@ class MQDao(ABC):
|
|
|
71
70
|
self._keyvalue_dao = KeyValueDAO()
|
|
72
71
|
self._time_based_flushing_started = False
|
|
73
72
|
self.buffer: Union[AutoflushBuffer, List] = None
|
|
74
|
-
|
|
73
|
+
if MQ_TIMING:
|
|
74
|
+
self._flush_events = []
|
|
75
|
+
self.stop = self._stop_timed
|
|
76
|
+
self.send_message = self._send_message_timed
|
|
77
|
+
self._bulk_publish = self._bulk_publish_timed
|
|
78
|
+
else:
|
|
79
|
+
self.stop = self._stop
|
|
75
80
|
|
|
76
81
|
@abstractmethod
|
|
77
82
|
def _bulk_publish(self, buffer, channel=MQ_CHANNEL, serializer=msgpack.dumps):
|
|
78
83
|
raise NotImplementedError()
|
|
79
84
|
|
|
85
|
+
def _bulk_publish_timed(self, buffer, channel=MQ_CHANNEL, serializer=msgpack.dumps):
|
|
86
|
+
raise NotImplementedError()
|
|
87
|
+
|
|
80
88
|
def bulk_publish(self, buffer):
|
|
81
89
|
"""Publish it."""
|
|
82
90
|
# self.logger.info(f"Going to flush {len(buffer)} to MQ...")
|
|
@@ -134,12 +142,10 @@ class MQDao(ABC):
|
|
|
134
142
|
"""Create the buffer."""
|
|
135
143
|
if not self.started:
|
|
136
144
|
if flowcept.configs.DB_FLUSH_MODE == "online":
|
|
137
|
-
# msg = "Starting MQ time-based flushing! bundle: "
|
|
138
|
-
# self.logger.debug(msg+f"{exec_bundle_id}; interceptor id: {interceptor_instance_id}")
|
|
139
145
|
self.buffer = AutoflushBuffer(
|
|
146
|
+
flush_function=self.bulk_publish,
|
|
140
147
|
max_size=MQ_BUFFER_SIZE,
|
|
141
148
|
flush_interval=MQ_INSERTION_BUFFER_TIME,
|
|
142
|
-
flush_function=self.bulk_publish,
|
|
143
149
|
)
|
|
144
150
|
self.register_time_based_thread_init(interceptor_instance_id, exec_bundle_id)
|
|
145
151
|
self._time_based_flushing_started = True
|
|
@@ -158,19 +164,10 @@ class MQDao(ABC):
|
|
|
158
164
|
self.bulk_publish(self.buffer)
|
|
159
165
|
self.buffer = list()
|
|
160
166
|
|
|
161
|
-
def
|
|
162
|
-
"""Stop it."""
|
|
167
|
+
def _stop_timed(self, interceptor_instance_id: str, bundle_exec_id: int = None):
|
|
163
168
|
t1 = time()
|
|
164
|
-
|
|
165
|
-
self.logger.debug(msg0 + f"{bundle_exec_id}; interceptor id: {interceptor_instance_id}")
|
|
166
|
-
self._close_buffer()
|
|
167
|
-
msg = "Flushed MQ for last time! Send stop msg. bundle: "
|
|
168
|
-
self.logger.debug(msg + f"{bundle_exec_id}; interceptor id: {interceptor_instance_id}")
|
|
169
|
-
self._send_mq_dao_time_thread_stop(interceptor_instance_id, bundle_exec_id)
|
|
170
|
-
self.started = False
|
|
171
|
-
|
|
169
|
+
self._stop(interceptor_instance_id, bundle_exec_id)
|
|
172
170
|
t2 = time()
|
|
173
|
-
|
|
174
171
|
self._flush_events.append(["final", t1, t2, t2 - t1, "n/a"])
|
|
175
172
|
|
|
176
173
|
with open(f"{MQ_TYPE}_{interceptor_instance_id}_{MQ_TYPE}_flush_events.csv", "w", newline="") as file:
|
|
@@ -178,9 +175,15 @@ class MQDao(ABC):
|
|
|
178
175
|
writer.writerow(["type", "start", "end", "duration", "size"])
|
|
179
176
|
writer.writerows(self._flush_events)
|
|
180
177
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
178
|
+
def _stop(self, interceptor_instance_id: str, bundle_exec_id: int = None):
|
|
179
|
+
"""Stop it."""
|
|
180
|
+
msg0 = "MQ publisher received stop signal! bundle: "
|
|
181
|
+
self.logger.debug(msg0 + f"{bundle_exec_id}; interceptor id: {interceptor_instance_id}")
|
|
182
|
+
self._close_buffer()
|
|
183
|
+
msg = "Flushed MQ for last time! Send stop msg. bundle: "
|
|
184
|
+
self.logger.debug(msg + f"{bundle_exec_id}; interceptor id: {interceptor_instance_id}")
|
|
185
|
+
self._send_mq_dao_time_thread_stop(interceptor_instance_id, bundle_exec_id)
|
|
186
|
+
self.started = False
|
|
184
187
|
|
|
185
188
|
def _send_mq_dao_time_thread_stop(self, interceptor_instance_id, exec_bundle_id=None):
|
|
186
189
|
# These control_messages are handled by the document inserter
|
|
@@ -205,6 +208,11 @@ class MQDao(ABC):
|
|
|
205
208
|
"""Send a message."""
|
|
206
209
|
raise NotImplementedError()
|
|
207
210
|
|
|
211
|
+
@abstractmethod
|
|
212
|
+
def _send_message_timed(self, message: dict, channel=MQ_CHANNEL, serializer=msgpack.dumps):
|
|
213
|
+
"""Send a message."""
|
|
214
|
+
raise NotImplementedError()
|
|
215
|
+
|
|
208
216
|
@abstractmethod
|
|
209
217
|
def message_listener(self, message_handler: Callable):
|
|
210
218
|
"""Get message listener."""
|
|
@@ -1,18 +1,15 @@
|
|
|
1
1
|
"""MQ kafka module."""
|
|
2
2
|
|
|
3
3
|
from typing import Callable
|
|
4
|
-
|
|
5
|
-
import msgpack
|
|
6
4
|
from time import time
|
|
5
|
+
import msgpack
|
|
7
6
|
|
|
8
7
|
from confluent_kafka import Producer, Consumer, KafkaError
|
|
9
8
|
from confluent_kafka.admin import AdminClient
|
|
10
9
|
|
|
11
10
|
from flowcept.commons.daos.mq_dao.mq_dao_base import MQDao
|
|
12
|
-
from flowcept.commons.utils import perf_log
|
|
13
11
|
from flowcept.configs import (
|
|
14
12
|
MQ_CHANNEL,
|
|
15
|
-
PERF_LOG,
|
|
16
13
|
MQ_HOST,
|
|
17
14
|
MQ_PORT,
|
|
18
15
|
)
|
|
@@ -67,35 +64,46 @@ class MQDaoKafka(MQDao):
|
|
|
67
64
|
def send_message(self, message: dict, channel=MQ_CHANNEL, serializer=msgpack.dumps):
|
|
68
65
|
"""Send the message."""
|
|
69
66
|
self._producer.produce(channel, key=channel, value=serializer(message))
|
|
70
|
-
t1 = time()
|
|
71
67
|
self._producer.flush()
|
|
68
|
+
|
|
69
|
+
def _send_message_timed(self, message: dict, channel=MQ_CHANNEL, serializer=msgpack.dumps):
|
|
70
|
+
t1 = time()
|
|
71
|
+
self.send_message(message, channel, serializer)
|
|
72
72
|
t2 = time()
|
|
73
73
|
self._flush_events.append(["single", t1, t2, t2 - t1, len(str(message).encode())])
|
|
74
74
|
|
|
75
75
|
def _bulk_publish(self, buffer, channel=MQ_CHANNEL, serializer=msgpack.dumps):
|
|
76
|
+
for message in buffer:
|
|
77
|
+
try:
|
|
78
|
+
self._producer.produce(channel, key=channel, value=serializer(message))
|
|
79
|
+
except Exception as e:
|
|
80
|
+
self.logger.exception(e)
|
|
81
|
+
self.logger.error("Some messages couldn't be flushed! Check the messages' contents!")
|
|
82
|
+
self.logger.error(f"Message that caused error: {message}")
|
|
83
|
+
try:
|
|
84
|
+
self._producer.flush()
|
|
85
|
+
self.logger.info(f"Flushed {len(buffer)} msgs to MQ!")
|
|
86
|
+
except Exception as e:
|
|
87
|
+
self.logger.exception(e)
|
|
88
|
+
|
|
89
|
+
def _bulk_publish_timed(self, buffer, channel=MQ_CHANNEL, serializer=msgpack.dumps):
|
|
76
90
|
total = 0
|
|
77
91
|
for message in buffer:
|
|
78
92
|
try:
|
|
79
|
-
self.logger.debug(f"Going to send Message:\n\t[BEGIN_MSG]{message}\n[END_MSG]\t")
|
|
80
93
|
self._producer.produce(channel, key=channel, value=serializer(message))
|
|
81
94
|
total += len(str(message).encode())
|
|
82
95
|
except Exception as e:
|
|
83
96
|
self.logger.exception(e)
|
|
84
97
|
self.logger.error("Some messages couldn't be flushed! Check the messages' contents!")
|
|
85
98
|
self.logger.error(f"Message that caused error: {message}")
|
|
86
|
-
t0 = 0
|
|
87
|
-
if PERF_LOG:
|
|
88
|
-
t0 = time()
|
|
89
99
|
try:
|
|
90
100
|
t1 = time()
|
|
91
101
|
self._producer.flush()
|
|
92
102
|
t2 = time()
|
|
93
103
|
self._flush_events.append(["bulk", t1, t2, t2 - t1, total])
|
|
94
|
-
|
|
95
104
|
self.logger.info(f"Flushed {len(buffer)} msgs to MQ!")
|
|
96
105
|
except Exception as e:
|
|
97
106
|
self.logger.exception(e)
|
|
98
|
-
perf_log("mq_pipe_flush", t0)
|
|
99
107
|
|
|
100
108
|
def liveness_test(self):
|
|
101
109
|
"""Get the livelyness of it."""
|
|
@@ -9,8 +9,7 @@ import mochi.mofka.client as mofka
|
|
|
9
9
|
from mochi.mofka.client import ThreadPool, AdaptiveBatchSize
|
|
10
10
|
|
|
11
11
|
from flowcept.commons.daos.mq_dao.mq_dao_base import MQDao
|
|
12
|
-
from flowcept.
|
|
13
|
-
from flowcept.configs import PERF_LOG, MQ_SETTINGS, MQ_CHANNEL
|
|
12
|
+
from flowcept.configs import MQ_SETTINGS, MQ_CHANNEL
|
|
14
13
|
|
|
15
14
|
|
|
16
15
|
class MQDaoMofka(MQDao):
|
|
@@ -56,12 +55,31 @@ class MQDaoMofka(MQDao):
|
|
|
56
55
|
def send_message(self, message: dict, channel=MQ_CHANNEL, serializer=msgpack.dumps):
|
|
57
56
|
"""Send a single message to Mofka."""
|
|
58
57
|
self.producer.push(metadata=message) # using metadata to send data
|
|
59
|
-
t1 = time()
|
|
60
58
|
self.producer.flush()
|
|
59
|
+
|
|
60
|
+
def _send_message_timed(self, message: dict, channel=MQ_CHANNEL, serializer=msgpack.dumps):
|
|
61
|
+
t1 = time()
|
|
62
|
+
self.send_message(message, channel, serializer)
|
|
61
63
|
t2 = time()
|
|
62
64
|
self._flush_events.append(["single", t1, t2, t2 - t1, len(str(message).encode())])
|
|
63
65
|
|
|
64
66
|
def _bulk_publish(self, buffer, channel=MQ_CHANNEL, serializer=msgpack.dumps):
|
|
67
|
+
try:
|
|
68
|
+
self.logger.debug(f"Going to send Message:\n\t[BEGIN_MSG]{buffer}\n[END_MSG]\t")
|
|
69
|
+
for m in buffer:
|
|
70
|
+
self.producer.push(m)
|
|
71
|
+
|
|
72
|
+
except Exception as e:
|
|
73
|
+
self.logger.exception(e)
|
|
74
|
+
self.logger.error("Some messages couldn't be flushed! Check the messages' contents!")
|
|
75
|
+
self.logger.error(f"Message that caused error: {buffer}")
|
|
76
|
+
try:
|
|
77
|
+
self.producer.flush()
|
|
78
|
+
self.logger.info(f"Flushed {len(buffer)} msgs to MQ!")
|
|
79
|
+
except Exception as e:
|
|
80
|
+
self.logger.exception(e)
|
|
81
|
+
|
|
82
|
+
def _bulk_publish_timed(self, buffer, channel=MQ_CHANNEL, serializer=msgpack.dumps):
|
|
65
83
|
total = 0
|
|
66
84
|
try:
|
|
67
85
|
self.logger.debug(f"Going to send Message:\n\t[BEGIN_MSG]{buffer}\n[END_MSG]\t")
|
|
@@ -74,19 +92,14 @@ class MQDaoMofka(MQDao):
|
|
|
74
92
|
self.logger.exception(e)
|
|
75
93
|
self.logger.error("Some messages couldn't be flushed! Check the messages' contents!")
|
|
76
94
|
self.logger.error(f"Message that caused error: {buffer}")
|
|
77
|
-
t0 = 0
|
|
78
|
-
if PERF_LOG:
|
|
79
|
-
t0 = time()
|
|
80
95
|
try:
|
|
81
96
|
t1 = time()
|
|
82
97
|
self.producer.flush()
|
|
83
98
|
t2 = time()
|
|
84
99
|
self._flush_events.append(["bulk", t1, t2, t2 - t1, total])
|
|
85
|
-
|
|
86
100
|
self.logger.info(f"Flushed {len(buffer)} msgs to MQ!")
|
|
87
101
|
except Exception as e:
|
|
88
102
|
self.logger.exception(e)
|
|
89
|
-
perf_log("mq_pipe_flush", t0)
|
|
90
103
|
|
|
91
104
|
def liveness_test(self):
|
|
92
105
|
"""Test Mofka Liveness."""
|
|
@@ -7,11 +7,7 @@ import msgpack
|
|
|
7
7
|
from time import time, sleep
|
|
8
8
|
|
|
9
9
|
from flowcept.commons.daos.mq_dao.mq_dao_base import MQDao
|
|
10
|
-
from flowcept.
|
|
11
|
-
from flowcept.configs import (
|
|
12
|
-
MQ_CHANNEL,
|
|
13
|
-
PERF_LOG,
|
|
14
|
-
)
|
|
10
|
+
from flowcept.configs import MQ_CHANNEL
|
|
15
11
|
|
|
16
12
|
|
|
17
13
|
class MQDaoRedis(MQDao):
|
|
@@ -60,25 +56,41 @@ class MQDaoRedis(MQDao):
|
|
|
60
56
|
|
|
61
57
|
def send_message(self, message: dict, channel=MQ_CHANNEL, serializer=msgpack.dumps):
|
|
62
58
|
"""Send the message."""
|
|
63
|
-
t1 = time()
|
|
64
59
|
self._producer.publish(channel, serializer(message))
|
|
60
|
+
|
|
61
|
+
def _send_message_timed(self, message: dict, channel=MQ_CHANNEL, serializer=msgpack.dumps):
|
|
62
|
+
"""Send the message using timing for performance evaluation."""
|
|
63
|
+
t1 = time()
|
|
64
|
+
self.send_message(message, channel, serializer)
|
|
65
65
|
t2 = time()
|
|
66
66
|
self._flush_events.append(["single", t1, t2, t2 - t1, len(str(message).encode())])
|
|
67
67
|
|
|
68
68
|
def _bulk_publish(self, buffer, channel=MQ_CHANNEL, serializer=msgpack.dumps):
|
|
69
|
+
pipe = self._producer.pipeline()
|
|
70
|
+
for message in buffer:
|
|
71
|
+
try:
|
|
72
|
+
pipe.publish(channel, serializer(message))
|
|
73
|
+
except Exception as e:
|
|
74
|
+
self.logger.exception(e)
|
|
75
|
+
self.logger.error("Some messages couldn't be flushed! Check the messages' contents!")
|
|
76
|
+
self.logger.error(f"Message that caused error: {message}")
|
|
77
|
+
try:
|
|
78
|
+
pipe.execute()
|
|
79
|
+
self.logger.debug(f"Flushed {len(buffer)} msgs to MQ!")
|
|
80
|
+
except Exception as e:
|
|
81
|
+
self.logger.exception(e)
|
|
82
|
+
|
|
83
|
+
def _bulk_publish_timed(self, buffer, channel=MQ_CHANNEL, serializer=msgpack.dumps):
|
|
69
84
|
total = 0
|
|
70
85
|
pipe = self._producer.pipeline()
|
|
71
86
|
for message in buffer:
|
|
72
87
|
try:
|
|
73
88
|
total += len(str(message).encode())
|
|
74
|
-
pipe.publish(
|
|
89
|
+
pipe.publish(channel, serializer(message))
|
|
75
90
|
except Exception as e:
|
|
76
91
|
self.logger.exception(e)
|
|
77
92
|
self.logger.error("Some messages couldn't be flushed! Check the messages' contents!")
|
|
78
93
|
self.logger.error(f"Message that caused error: {message}")
|
|
79
|
-
t0 = 0
|
|
80
|
-
if PERF_LOG:
|
|
81
|
-
t0 = time()
|
|
82
94
|
try:
|
|
83
95
|
t1 = time()
|
|
84
96
|
pipe.execute()
|
|
@@ -87,7 +99,6 @@ class MQDaoRedis(MQDao):
|
|
|
87
99
|
self.logger.debug(f"Flushed {len(buffer)} msgs to MQ!")
|
|
88
100
|
except Exception as e:
|
|
89
101
|
self.logger.exception(e)
|
|
90
|
-
perf_log("mq_pipe_execute", t0)
|
|
91
102
|
|
|
92
103
|
def liveness_test(self):
|
|
93
104
|
"""Get the livelyness of it."""
|
flowcept/configs.py
CHANGED
|
@@ -73,9 +73,9 @@ MQ_CHANNEL = settings["mq"].get("channel", "interception")
|
|
|
73
73
|
MQ_PASSWORD = settings["mq"].get("password", None)
|
|
74
74
|
MQ_HOST = os.getenv("MQ_HOST", settings["mq"].get("host", "localhost"))
|
|
75
75
|
MQ_PORT = int(os.getenv("MQ_PORT", settings["mq"].get("port", "6379")))
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
76
|
+
MQ_BUFFER_SIZE = settings["mq"].get("buffer_size", None)
|
|
77
|
+
MQ_INSERTION_BUFFER_TIME = settings["mq"].get("insertion_buffer_time_secs", None)
|
|
78
|
+
MQ_TIMING = settings["mq"].get("timing", False)
|
|
79
79
|
MQ_CHUNK_SIZE = int(settings["mq"].get("chunk_size", -1))
|
|
80
80
|
|
|
81
81
|
#####################
|
|
@@ -127,7 +127,7 @@ if not LMDB_ENABLED and not MONGO_ENABLED:
|
|
|
127
127
|
##########################
|
|
128
128
|
db_buffer_settings = settings["db_buffer"]
|
|
129
129
|
# In seconds:
|
|
130
|
-
INSERTION_BUFFER_TIME =
|
|
130
|
+
INSERTION_BUFFER_TIME = db_buffer_settings.get("insertion_buffer_time_secs", None)
|
|
131
131
|
ADAPTIVE_DB_BUFFER_SIZE = db_buffer_settings.get("adaptive_buffer_size", True)
|
|
132
132
|
DB_MAX_BUFFER_SIZE = int(db_buffer_settings.get("max_buffer_size", 50))
|
|
133
133
|
DB_MIN_BUFFER_SIZE = max(1, int(db_buffer_settings.get("min_buffer_size", 10)))
|
|
@@ -21,32 +21,6 @@ from flowcept.flowceptor.adapters.instrumentation_interceptor import Instrumenta
|
|
|
21
21
|
|
|
22
22
|
def get_run_spec_data(task_msg: TaskObject, run_spec):
|
|
23
23
|
"""Get the run specs."""
|
|
24
|
-
# def _get_arg(arg_name):
|
|
25
|
-
# if type(run_spec) == dict:
|
|
26
|
-
# return run_spec.get(arg_name, None)
|
|
27
|
-
# elif hasattr(run_spec, arg_name):
|
|
28
|
-
# return getattr(run_spec, arg_name)
|
|
29
|
-
# return None
|
|
30
|
-
#
|
|
31
|
-
# def _parse_dask_tuple(_tuple: tuple):
|
|
32
|
-
# forth_elem = None
|
|
33
|
-
# if len(_tuple) == 3:
|
|
34
|
-
# _, _, value_tuple = _tuple
|
|
35
|
-
# elif len(_tuple) == 4:
|
|
36
|
-
# _, _, value_tuple, forth_elem = _tuple
|
|
37
|
-
#
|
|
38
|
-
# _, value = value_tuple
|
|
39
|
-
# if len(value) == 1: # Value is always an array here
|
|
40
|
-
# value = value[0]
|
|
41
|
-
# ret_obj = {"value": value}
|
|
42
|
-
#
|
|
43
|
-
# if forth_elem is not None and type(forth_elem) == dict:
|
|
44
|
-
# ret_obj.update(forth_elem)
|
|
45
|
-
# else:
|
|
46
|
-
# pass # We don't know yet what to do if this happens. So just pass.
|
|
47
|
-
#
|
|
48
|
-
# return ret_obj
|
|
49
|
-
|
|
50
24
|
func = run_spec[0]
|
|
51
25
|
task_msg.activity_id = func.__name__
|
|
52
26
|
args = run_spec[1]
|
|
@@ -91,7 +65,7 @@ class DaskWorkerInterceptor(BaseInterceptor):
|
|
|
91
65
|
self._plugin_key = plugin_key
|
|
92
66
|
self._worker = None
|
|
93
67
|
self.kind = kind
|
|
94
|
-
# super().__init__ goes to setup_worker.
|
|
68
|
+
# super().__init__ goes to setup_worker. I'm leaving this commented here as a reminder.
|
|
95
69
|
|
|
96
70
|
def setup_worker(self, worker):
|
|
97
71
|
"""Set the worker.
|
|
@@ -101,7 +75,8 @@ class DaskWorkerInterceptor(BaseInterceptor):
|
|
|
101
75
|
"""
|
|
102
76
|
self._worker = worker
|
|
103
77
|
super().__init__(plugin_key=self._plugin_key, kind=self.kind)
|
|
104
|
-
|
|
78
|
+
self._worker.flowcept_tasks = {}
|
|
79
|
+
# TODO: :refactor: Below is just to avoid the auto-generation of workflow id, which doesn't make sense in Dask.
|
|
105
80
|
self._generated_workflow_id = True
|
|
106
81
|
super().start(bundle_exec_id=self._worker.scheduler.address)
|
|
107
82
|
|
|
@@ -129,6 +104,8 @@ class DaskWorkerInterceptor(BaseInterceptor):
|
|
|
129
104
|
task_msg.address = self._worker.worker_address
|
|
130
105
|
if self.settings.worker_create_timestamps:
|
|
131
106
|
task_msg.started_at = get_utc_now()
|
|
107
|
+
|
|
108
|
+
self._worker.flowcept_tasks[task_id] = task_msg
|
|
132
109
|
elif ts.state == "memory":
|
|
133
110
|
task_msg.status = Status.FINISHED
|
|
134
111
|
if self.settings.worker_create_timestamps:
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
"""Dask plugin module."""
|
|
2
2
|
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
3
5
|
from distributed import Client, WorkerPlugin
|
|
4
6
|
|
|
5
7
|
from flowcept import WorkflowObject
|
|
8
|
+
from flowcept.commons.flowcept_dataclasses.task_object import TaskObject
|
|
6
9
|
from flowcept.configs import INSTRUMENTATION
|
|
7
10
|
from flowcept.flowceptor.adapters.dask.dask_interceptor import (
|
|
8
11
|
DaskWorkerInterceptor,
|
|
@@ -10,38 +13,6 @@ from flowcept.flowceptor.adapters.dask.dask_interceptor import (
|
|
|
10
13
|
from flowcept.flowceptor.adapters.instrumentation_interceptor import InstrumentationInterceptor
|
|
11
14
|
|
|
12
15
|
|
|
13
|
-
# def _set_workflow_on_scheduler(
|
|
14
|
-
# dask_scheduler=None,
|
|
15
|
-
# workflow_id=None,
|
|
16
|
-
# custom_metadata: dict = None,
|
|
17
|
-
# campaign_id: str = None,
|
|
18
|
-
# workflow_name: str = None,
|
|
19
|
-
# used: dict = None,
|
|
20
|
-
# ):
|
|
21
|
-
# custom_metadata = custom_metadata or {}
|
|
22
|
-
# wf_obj = WorkflowObject()
|
|
23
|
-
# wf_obj.workflow_id = workflow_id
|
|
24
|
-
# custom_metadata.update(
|
|
25
|
-
# {
|
|
26
|
-
# "workflow_type": "DaskWorkflow",
|
|
27
|
-
# "scheduler": dask_scheduler.address_safe,
|
|
28
|
-
# "scheduler_id": dask_scheduler.id,
|
|
29
|
-
# "scheduler_pid": dask_scheduler.proc.pid,
|
|
30
|
-
# "clients": len(dask_scheduler.clients),
|
|
31
|
-
# "n_workers": len(dask_scheduler.workers),
|
|
32
|
-
# }
|
|
33
|
-
# )
|
|
34
|
-
# wf_obj.custom_metadata = custom_metadata
|
|
35
|
-
# wf_obj.used = used
|
|
36
|
-
# wf_obj.campaign_id = campaign_id
|
|
37
|
-
# wf_obj.name = workflow_name
|
|
38
|
-
#
|
|
39
|
-
# interceptor = BaseInterceptor(plugin_key="dask")
|
|
40
|
-
# interceptor.start(bundle_exec_id=dask_scheduler.address)
|
|
41
|
-
# interceptor.send_workflow_message(wf_obj)
|
|
42
|
-
# interceptor.stop()
|
|
43
|
-
|
|
44
|
-
|
|
45
16
|
def _set_workflow_on_workers(dask_worker, workflow_id, campaign_id=None):
|
|
46
17
|
setattr(dask_worker, "current_workflow_id", workflow_id)
|
|
47
18
|
if campaign_id:
|
|
@@ -53,6 +24,23 @@ def set_workflow_info_on_workers(dask_client: Client, wf_obj: WorkflowObject):
|
|
|
53
24
|
dask_client.run(_set_workflow_on_workers, workflow_id=wf_obj.workflow_id, campaign_id=wf_obj.campaign_id)
|
|
54
25
|
|
|
55
26
|
|
|
27
|
+
def get_flowcept_task() -> Optional[TaskObject]:
|
|
28
|
+
"""Get the Flowcept Task Object inside a Worker's task."""
|
|
29
|
+
from distributed import get_worker
|
|
30
|
+
from distributed.worker import thread_state
|
|
31
|
+
|
|
32
|
+
worker = get_worker()
|
|
33
|
+
try:
|
|
34
|
+
task_id = thread_state.key if hasattr(thread_state, "key") else None
|
|
35
|
+
if hasattr(worker, "flowcept_tasks") and task_id in worker.flowcept_tasks:
|
|
36
|
+
return worker.flowcept_tasks[task_id]
|
|
37
|
+
else:
|
|
38
|
+
return None
|
|
39
|
+
except Exception as e:
|
|
40
|
+
print(e)
|
|
41
|
+
return None
|
|
42
|
+
|
|
43
|
+
|
|
56
44
|
class FlowceptDaskWorkerAdapter(WorkerPlugin):
|
|
57
45
|
"""Dask worker adapter."""
|
|
58
46
|
|
|
@@ -71,10 +71,10 @@ class DocumentInserter:
|
|
|
71
71
|
self._bundle_exec_id = bundle_exec_id
|
|
72
72
|
self.check_safe_stops = check_safe_stops
|
|
73
73
|
self.buffer: AutoflushBuffer = AutoflushBuffer(
|
|
74
|
-
max_size=self._curr_max_buffer_size,
|
|
75
|
-
flush_interval=INSERTION_BUFFER_TIME,
|
|
76
74
|
flush_function=DocumentInserter.flush_function,
|
|
77
75
|
flush_function_kwargs={"logger": self.logger, "doc_daos": self._doc_daos},
|
|
76
|
+
max_size=self._curr_max_buffer_size,
|
|
77
|
+
flush_interval=INSERTION_BUFFER_TIME,
|
|
78
78
|
)
|
|
79
79
|
|
|
80
80
|
def _set_buffer_size(self):
|
flowcept/version.py
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
flowcept/__init__.py,sha256=CukmdzTUvm6Y_plTKPq4kKn7w9LdR36j7V_C_UQyjhU,2011
|
|
2
|
-
flowcept/configs.py,sha256=
|
|
3
|
-
flowcept/version.py,sha256=
|
|
2
|
+
flowcept/configs.py,sha256=_-jhoI_HGKjzymjYTlDuysbM38Gr2aunc0Q-Stlmcwk,7511
|
|
3
|
+
flowcept/version.py,sha256=sgsQa7sBlHkp-P60Bs4HRcOzfCc2iDmfQsjJbMii7Xg,306
|
|
4
4
|
flowcept/analytics/__init__.py,sha256=46q-7vsHq_ddPNrzNnDgEOiRgvlx-5Ggu2ocyROMV0w,641
|
|
5
5
|
flowcept/analytics/analytics_utils.py,sha256=FRJdBtQa7Hrk2oR_FFhmhmMf3X6YyZ4nbH5RIYh7KL4,8753
|
|
6
6
|
flowcept/analytics/data_augmentation.py,sha256=Dyr5x316Zf-k1e8rVoQMCpFOrklYVHjfejRPrtoycmc,1641
|
|
7
7
|
flowcept/analytics/plot.py,sha256=L56y1HRnTE6-Fxs62Y0rV2OtDwjSwgSP3yLdalkiRBQ,2932
|
|
8
8
|
flowcept/commons/__init__.py,sha256=W94CqapS0IGuuIGHHaz4sNuuiYhgtJWtpDEbnI0pGwI,26
|
|
9
|
-
flowcept/commons/autoflush_buffer.py,sha256=
|
|
9
|
+
flowcept/commons/autoflush_buffer.py,sha256=8M0fcIeHck-mSGQ2HFpW3_Af8-dHswhIbUMX5FATm48,2589
|
|
10
10
|
flowcept/commons/flowcept_logger.py,sha256=0asRucrDMeRXvsdhuCmH6lWO7lAt_Z5o5uW7rrQhcjc,1857
|
|
11
11
|
flowcept/commons/query_utils.py,sha256=3tyK5VYA10iDtmtzNwa8OQGn93DBxsu6rTjHDphftSc,2208
|
|
12
12
|
flowcept/commons/settings_factory.py,sha256=vpvnpqabPKK-mzoZ5iLdnefpemW1MldDOZhii_m9wNk,1814
|
|
@@ -19,10 +19,10 @@ flowcept/commons/daos/docdb_dao/docdb_dao_base.py,sha256=YbfSVJPwZGK2GBYkeapRC83
|
|
|
19
19
|
flowcept/commons/daos/docdb_dao/lmdb_dao.py,sha256=dJOLgCx_lwdz6MKiMpM_UE4rm0angDCPaVz_WU5KqIA,10407
|
|
20
20
|
flowcept/commons/daos/docdb_dao/mongodb_dao.py,sha256=-Kxjep1FbjKiGjvzyvePVHDf-Q1lOIce1EzBURSKubc,38037
|
|
21
21
|
flowcept/commons/daos/mq_dao/__init__.py,sha256=Xxm4FmbBUZDQ7XIAmSFbeKE_AdHsbgFmSuftvMWSykQ,21
|
|
22
|
-
flowcept/commons/daos/mq_dao/mq_dao_base.py,sha256=
|
|
23
|
-
flowcept/commons/daos/mq_dao/mq_dao_kafka.py,sha256=
|
|
24
|
-
flowcept/commons/daos/mq_dao/mq_dao_mofka.py,sha256=
|
|
25
|
-
flowcept/commons/daos/mq_dao/mq_dao_redis.py,sha256=
|
|
22
|
+
flowcept/commons/daos/mq_dao/mq_dao_base.py,sha256=EAqOhy7Q8V29JFDG8C50nRK34KsPxEICkG4elk4ZfX8,9020
|
|
23
|
+
flowcept/commons/daos/mq_dao/mq_dao_kafka.py,sha256=bf-bZvWw9JJk8Kdfzx2UkAnQC95rSrKXDEyYkrcncOk,4400
|
|
24
|
+
flowcept/commons/daos/mq_dao/mq_dao_mofka.py,sha256=aZ810wN5Wkjk7oRUxDWJWOIREUsmq57oI4AxY1bWBuk,3940
|
|
25
|
+
flowcept/commons/daos/mq_dao/mq_dao_redis.py,sha256=Br97SoDIkt4dHH937Yjg3wtkn1xGT-x9t-8E3VD5TeU,4277
|
|
26
26
|
flowcept/commons/flowcept_dataclasses/__init__.py,sha256=8KkiJh0WSRAB50waVluxCSI8Tb9X1L9nup4c8RN3ulc,30
|
|
27
27
|
flowcept/commons/flowcept_dataclasses/base_settings_dataclasses.py,sha256=Cjw2PGYtZDfnwecz6G3S42Ncmxj7AIZVEBx05bsxRUo,399
|
|
28
28
|
flowcept/commons/flowcept_dataclasses/task_object.py,sha256=3DD5ZNMz7EVILS9PRkQ3khboav7lIKoUC5W6sKMFauQ,4694
|
|
@@ -45,8 +45,8 @@ flowcept/flowceptor/adapters/instrumentation_interceptor.py,sha256=DhK2bBnpghqPS
|
|
|
45
45
|
flowcept/flowceptor/adapters/interceptor_state_manager.py,sha256=xRzmi5YFKBEqNtX8F5s6XlMTRe27ml4BmQtBO4WtG2c,919
|
|
46
46
|
flowcept/flowceptor/adapters/dask/__init__.py,sha256=GKreb5L_nliD2BEckyB943zOQ-b6Gn1fLDj81FqSK2Y,23
|
|
47
47
|
flowcept/flowceptor/adapters/dask/dask_dataclasses.py,sha256=6LTG-kdcc6AUuVINvkqB5QHw6pchg1aMqj0sdWt2Ef8,580
|
|
48
|
-
flowcept/flowceptor/adapters/dask/dask_interceptor.py,sha256=
|
|
49
|
-
flowcept/flowceptor/adapters/dask/dask_plugins.py,sha256=
|
|
48
|
+
flowcept/flowceptor/adapters/dask/dask_interceptor.py,sha256=Dzrwu9Y9A6k2Qq8tZKXx3zmi-CpmtFrJehUTfNjZxDM,5827
|
|
49
|
+
flowcept/flowceptor/adapters/dask/dask_plugins.py,sha256=s1ENAi9N61PC_6RiFvOYhJsgWzSm_lFWm3w87V-R1YY,2473
|
|
50
50
|
flowcept/flowceptor/adapters/mlflow/__init__.py,sha256=3mzHrvh1XQOy68qx1A3so9Nq27tIb0i2mSXfv3F6gZg,25
|
|
51
51
|
flowcept/flowceptor/adapters/mlflow/interception_event_handler.py,sha256=-SsIRdOcZjQUTzWgsZ41ouqpla4Qd32jIWXIAGU1pPw,494
|
|
52
52
|
flowcept/flowceptor/adapters/mlflow/mlflow_dao.py,sha256=dPEgCduiw14_pzT5WCjuokwaN7p5Tu7UvWS2rtGh4qk,4589
|
|
@@ -60,14 +60,14 @@ flowcept/flowceptor/adapters/zambeze/zambeze_dataclasses.py,sha256=nn9MxvcdzgmOa
|
|
|
60
60
|
flowcept/flowceptor/adapters/zambeze/zambeze_interceptor.py,sha256=Bjyi48JW0DXJLJuvwPxaD8zxxsSoEFgSoXl8YcbwFWk,3782
|
|
61
61
|
flowcept/flowceptor/consumers/__init__.py,sha256=foxtVEb2ZEe9g1slfYIKM4tIFv-He1l7XS--SYs7nlQ,28
|
|
62
62
|
flowcept/flowceptor/consumers/consumer_utils.py,sha256=JmyjQeZPqMj_yqFlxxw9k2_JZvZkAmX7kySV__YvEVc,5719
|
|
63
|
-
flowcept/flowceptor/consumers/document_inserter.py,sha256=
|
|
63
|
+
flowcept/flowceptor/consumers/document_inserter.py,sha256=rAK3rs3VNW5a6koesE05scQ1mR_4BhuxLurP10ipURs,9339
|
|
64
64
|
flowcept/instrumentation/__init__.py,sha256=M5bTmg80E4QyN91gUX3qfw_nbtJSXwGWcKxdZP3vJz0,34
|
|
65
65
|
flowcept/instrumentation/flowcept_loop.py,sha256=9Ap7-PfpNdwS7DaRDaB-R9G3X_G3RZvGVkNVUZAix5A,12164
|
|
66
66
|
flowcept/instrumentation/flowcept_task.py,sha256=l_BAYEUZ_SeBt8QJN_E9D9QcZVYRnW9qO_XRnqvmePE,5993
|
|
67
67
|
flowcept/instrumentation/flowcept_torch.py,sha256=KXA1HBwz8l5Qp7PkZ7nsbYlM8IcwWD_u04NxaAcZPzM,23395
|
|
68
68
|
flowcept/instrumentation/task_capture.py,sha256=u82r_SgzoVKyb6_SWtfB-meBUZgjrXvF5dxkH9vnMDs,4776
|
|
69
|
-
resources/sample_settings.yaml,sha256=
|
|
70
|
-
flowcept-0.8.
|
|
71
|
-
flowcept-0.8.
|
|
72
|
-
flowcept-0.8.
|
|
73
|
-
flowcept-0.8.
|
|
69
|
+
resources/sample_settings.yaml,sha256=eYMO3rlS4m1sjkgoKuRIYaTuZldiu50bN-E3Bu3on_I,3424
|
|
70
|
+
flowcept-0.8.4.dist-info/METADATA,sha256=aOyqBxuMdXSO5h4n9vAqLQDY7U3ZRRzJoHKTrgHYfoE,17543
|
|
71
|
+
flowcept-0.8.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
72
|
+
flowcept-0.8.4.dist-info/licenses/LICENSE,sha256=r5-2P6tFTuRGWT5TiX32s1y0tnp4cIqBEC1QjTaXe2k,1086
|
|
73
|
+
flowcept-0.8.4.dist-info/RECORD,,
|
resources/sample_settings.yaml
CHANGED
|
File without changes
|
|
File without changes
|