funboost 48.0__py3-none-any.whl → 48.2__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.
Potentially problematic release.
This version of funboost might be problematic. Click here for more details.
- funboost/__init__.py +1 -1
- funboost/constant.py +7 -0
- funboost/consumers/base_consumer.py +137 -68
- funboost/core/active_cousumer_info_getter.py +80 -0
- funboost/core/function_result_status_saver.py +1 -1
- funboost/function_result_web/__pycache__/functions.cpython-37.pyc +0 -0
- funboost/function_result_web/__pycache__/functions.cpython-39.pyc +0 -0
- funboost/function_result_web/app.py +104 -7
- funboost/function_result_web/functions.py +17 -4
- funboost/function_result_web/static/css/content_page_style.css +39 -0
- funboost/function_result_web/static/images/favicon.ico +0 -0
- funboost/function_result_web/static/js/bootstrap-datetimepicker.min.js +2 -0
- funboost/function_result_web/static/js/echarts.min.js +32478 -0
- funboost/function_result_web/static/js/moment-with-locales.min.js +1 -0
- funboost/function_result_web/static/js/select2.min.js +2 -0
- funboost/function_result_web/templates/about.html +67 -0
- funboost/function_result_web/templates/conusme_speed.html +217 -0
- funboost/function_result_web/templates/fun_result_table.html +433 -0
- funboost/function_result_web/templates/index.html +194 -423
- funboost/function_result_web/templates/index_backup.html +475 -0
- funboost/function_result_web/templates/index_/321/204/342/225/225/320/235/321/205/320/237/320/277/321/206/320/232/320/250/321/205/320/237/320/260.html +153 -0
- funboost/function_result_web/templates/queue_op.html +501 -0
- funboost/function_result_web/templates/running_consumer_by_ip.html +219 -0
- funboost/function_result_web/templates/running_consumer_by_queue_name.html +220 -0
- funboost/timing_job/timing_push.py +24 -24
- funboost/utils/dependency_packages_in_pythonpath/aioredis/readme.md +0 -6
- funboost/utils/dependency_packages_in_pythonpath/readme.md +0 -6
- {funboost-48.0.dist-info → funboost-48.2.dist-info}/METADATA +78 -76
- {funboost-48.0.dist-info → funboost-48.2.dist-info}/RECORD +33 -18
- {funboost-48.0.dist-info → funboost-48.2.dist-info}/WHEEL +1 -1
- {funboost-48.0.dist-info → funboost-48.2.dist-info}/LICENSE +0 -0
- {funboost-48.0.dist-info → funboost-48.2.dist-info}/entry_points.txt +0 -0
- {funboost-48.0.dist-info → funboost-48.2.dist-info}/top_level.txt +0 -0
funboost/__init__.py
CHANGED
funboost/constant.py
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
# coding= utf-8
|
|
2
|
+
from calendar import c
|
|
3
|
+
|
|
4
|
+
|
|
2
5
|
class BrokerEnum:
|
|
3
6
|
EMPTY = 'empty' # 空的实现,需要搭配 boost入参的 consumer_override_cls 和 publisher_override_cls使用,或者被继承。
|
|
4
7
|
|
|
@@ -106,3 +109,7 @@ class ConstStrForClassMethod:
|
|
|
106
109
|
CLS_MODULE = 'cls_module'
|
|
107
110
|
CLS_FILE = 'cls_file'
|
|
108
111
|
|
|
112
|
+
class RedisKeys:
|
|
113
|
+
REDIS_KEY_PAUSE_FLAG = 'funboost_pause_flag'
|
|
114
|
+
REDIS_KEY_STOP_FLAG = 'funboost_stop_flag'
|
|
115
|
+
QUEUE__MSG_COUNT_MAP = 'funboost_queue__msg_count_map'
|
|
@@ -74,7 +74,7 @@ from funboost.consumers.redis_filter import RedisFilter, RedisImpermanencyFilter
|
|
|
74
74
|
from funboost.factories.publisher_factotry import get_publisher
|
|
75
75
|
|
|
76
76
|
from funboost.utils import decorators, time_util, redis_manager
|
|
77
|
-
from funboost.constant import ConcurrentModeEnum, BrokerEnum, ConstStrForClassMethod
|
|
77
|
+
from funboost.constant import ConcurrentModeEnum, BrokerEnum, ConstStrForClassMethod,RedisKeys
|
|
78
78
|
from funboost.core import kill_remote_task
|
|
79
79
|
from funboost.core.exceptions import ExceptionForRequeue, ExceptionForPushToDlxqueue
|
|
80
80
|
|
|
@@ -164,19 +164,25 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
164
164
|
filter_class = RedisFilter if consumer_params.task_filtering_expire_seconds == 0 else RedisImpermanencyFilter
|
|
165
165
|
self._redis_filter = filter_class(self._redis_filter_key_name, consumer_params.task_filtering_expire_seconds)
|
|
166
166
|
|
|
167
|
-
self._unit_time_for_count = 10 # 每隔多少秒计数,显示单位时间内执行多少次,暂时固定为10秒。
|
|
168
|
-
self._execute_task_times_every_unit_time = 0 # 每单位时间执行了多少次任务。
|
|
169
167
|
self._lock_for_count_execute_task_times_every_unit_time = Lock()
|
|
170
|
-
self.
|
|
171
|
-
self.
|
|
172
|
-
self.
|
|
173
|
-
|
|
174
|
-
self.
|
|
175
|
-
self.
|
|
176
|
-
|
|
177
|
-
self.
|
|
178
|
-
self.
|
|
179
|
-
|
|
168
|
+
# self._unit_time_for_count = 10 # 每隔多少秒计数,显示单位时间内执行多少次,暂时固定为10秒。
|
|
169
|
+
# self._execute_task_times_every_unit_time = 0 # 每单位时间执行了多少次任务。
|
|
170
|
+
# self._execute_task_times_every_unit_time_fail =0 # 每单位时间执行了多少次任务失败。
|
|
171
|
+
# self._lock_for_count_execute_task_times_every_unit_time = Lock()
|
|
172
|
+
# self._current_time_for_execute_task_times_every_unit_time = time.time()
|
|
173
|
+
# self._consuming_function_cost_time_total_every_unit_time = 0
|
|
174
|
+
# self._last_execute_task_time = time.time() # 最近一次执行任务的时间。
|
|
175
|
+
# self._last_10s_execute_count = 0
|
|
176
|
+
# self._last_10s_execute_count_fail = 0
|
|
177
|
+
#
|
|
178
|
+
# self._last_show_remaining_execution_time = 0
|
|
179
|
+
# self._show_remaining_execution_time_interval = 300
|
|
180
|
+
#
|
|
181
|
+
# self._msg_num_in_broker = 0
|
|
182
|
+
# self._last_timestamp_when_has_task_in_queue = 0
|
|
183
|
+
# self._last_timestamp_print_msg_num = 0
|
|
184
|
+
|
|
185
|
+
self.metric_calculation = MetricCalculation(self)
|
|
180
186
|
|
|
181
187
|
self._result_persistence_helper: ResultPersistenceHelper
|
|
182
188
|
self._check_broker_exclusive_config()
|
|
@@ -189,8 +195,8 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
189
195
|
self._stop_flag = None
|
|
190
196
|
self._pause_flag = None # 暂停消费标志,从reids读取
|
|
191
197
|
self._last_show_pause_log_time = 0
|
|
192
|
-
self._redis_key_stop_flag = f'funboost_stop_flag
|
|
193
|
-
self._redis_key_pause_flag =
|
|
198
|
+
# self._redis_key_stop_flag = f'funboost_stop_flag'
|
|
199
|
+
# self._redis_key_pause_flag = RedisKeys.REDIS_KEY_PAUSE_FLAG
|
|
194
200
|
|
|
195
201
|
# 控频要用到的成员变量
|
|
196
202
|
self._last_submit_task_timestamp = 0
|
|
@@ -358,7 +364,7 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
358
364
|
self._distributed_consumer_statistics.run()
|
|
359
365
|
self.logger.warning(f'启动了分布式环境 使用 redis 的键 hearbeat:{self._queue_name} 统计活跃消费者 ,当前消费者唯一标识为 {self.consumer_identification}')
|
|
360
366
|
|
|
361
|
-
self.keep_circulating(60, block=False, daemon=False)(self.check_heartbeat_and_message_count)()
|
|
367
|
+
self.keep_circulating(60, block=False, daemon=False)(self.check_heartbeat_and_message_count)()
|
|
362
368
|
if self.consumer_params.is_support_remote_kill_task:
|
|
363
369
|
kill_remote_task.RemoteTaskKiller(self.queue_name, None).start_cycle_kill_task()
|
|
364
370
|
self.consumer_params.is_show_message_get_from_broker = True # 方便用户看到从消息队列取出来的消息的task_id,然后使用task_id杀死运行中的消息。
|
|
@@ -677,26 +683,7 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
677
683
|
p.execute()
|
|
678
684
|
|
|
679
685
|
with self._lock_for_count_execute_task_times_every_unit_time:
|
|
680
|
-
self.
|
|
681
|
-
self._consuming_function_cost_time_total_every_unit_time += time.time() - t_start_run_fun
|
|
682
|
-
self._last_execute_task_time = time.time()
|
|
683
|
-
if time.time() - self._current_time_for_execute_task_times_every_unit_time > self._unit_time_for_count:
|
|
684
|
-
avarage_function_spend_time = round(self._consuming_function_cost_time_total_every_unit_time / self._execute_task_times_every_unit_time, 4)
|
|
685
|
-
msg = f'{self._unit_time_for_count} 秒内执行了 {self._execute_task_times_every_unit_time} 次函数 [ {self.consuming_function.__name__} ] ,' \
|
|
686
|
-
f'函数平均运行耗时 {avarage_function_spend_time} 秒。 '
|
|
687
|
-
self.logger.info(msg)
|
|
688
|
-
if time.time() - self._last_show_remaining_execution_time > self._show_remaining_execution_time_interval:
|
|
689
|
-
self._msg_num_in_broker = self.publisher_of_same_queue.get_message_count()
|
|
690
|
-
if self._msg_num_in_broker != -1: # 有的中间件无法统计或没实现统计队列剩余数量的,统一返回的是-1,不显示这句话。
|
|
691
|
-
# msg += f''' ,预计还需要 {time_util.seconds_to_hour_minute_second(self._msg_num_in_broker * avarage_function_spend_time / active_consumer_num)} 时间 才能执行完成 {self._msg_num_in_broker}个剩余的任务'''
|
|
692
|
-
need_time = time_util.seconds_to_hour_minute_second(self._msg_num_in_broker / (self._execute_task_times_every_unit_time / self._unit_time_for_count) /
|
|
693
|
-
self._distributed_consumer_statistics.active_consumer_num)
|
|
694
|
-
msg += f''' 预计还需要 {need_time} 时间 才能执行完成 队列 {self.queue_name} 中的 {self._msg_num_in_broker} 个剩余任务'''
|
|
695
|
-
self.logger.info(msg)
|
|
696
|
-
self._last_show_remaining_execution_time = time.time()
|
|
697
|
-
self._current_time_for_execute_task_times_every_unit_time = time.time()
|
|
698
|
-
self._consuming_function_cost_time_total_every_unit_time = 0
|
|
699
|
-
self._execute_task_times_every_unit_time = 0
|
|
686
|
+
self.metric_calculation.cal(t_start_run_fun,current_function_result_status)
|
|
700
687
|
self.user_custom_record_process_info_func(current_function_result_status) # 两种方式都可以自定义,记录结果,建议继承方式,不使用boost中指定 user_custom_record_process_info_func
|
|
701
688
|
if self.consumer_params.user_custom_record_process_info_func:
|
|
702
689
|
self.consumer_params.user_custom_record_process_info_func(current_function_result_status)
|
|
@@ -850,24 +837,7 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
850
837
|
await simple_run_in_executor(push_result)
|
|
851
838
|
|
|
852
839
|
# 异步执行不存在线程并发,不需要加锁。
|
|
853
|
-
self.
|
|
854
|
-
self._consuming_function_cost_time_total_every_unit_time += time.time() - t_start_run_fun
|
|
855
|
-
self._last_execute_task_time = time.time()
|
|
856
|
-
if time.time() - self._current_time_for_execute_task_times_every_unit_time > self._unit_time_for_count:
|
|
857
|
-
avarage_function_spend_time = round(self._consuming_function_cost_time_total_every_unit_time / self._execute_task_times_every_unit_time, 4)
|
|
858
|
-
msg = f'{self._unit_time_for_count} 秒内执行了 {self._execute_task_times_every_unit_time} 次函数 [ {self.consuming_function.__name__} ] ,' \
|
|
859
|
-
f'函数平均运行耗时 {avarage_function_spend_time} 秒。 '
|
|
860
|
-
self.logger.info(msg)
|
|
861
|
-
if self._msg_num_in_broker != -1 and time.time() - self._last_show_remaining_execution_time > self._show_remaining_execution_time_interval: # 有的中间件无法统计或没实现统计队列剩余数量的,统一返回的是-1,不显示这句话。
|
|
862
|
-
# msg += f''' ,预计还需要 {time_util.seconds_to_hour_minute_second(self._msg_num_in_broker * avarage_function_spend_time / active_consumer_num)} 时间 才能执行完成 {self._msg_num_in_broker}个剩余的任务'''
|
|
863
|
-
need_time = time_util.seconds_to_hour_minute_second(self._msg_num_in_broker / (self._execute_task_times_every_unit_time / self._unit_time_for_count) /
|
|
864
|
-
self._distributed_consumer_statistics.active_consumer_num)
|
|
865
|
-
msg += f''' 预计还需要 {need_time} 时间 才能执行完成 队列 {self.queue_name} 中的 {self._msg_num_in_broker} 个剩余任务'''
|
|
866
|
-
self.logger.info(msg)
|
|
867
|
-
self._last_show_remaining_execution_time = time.time()
|
|
868
|
-
self._current_time_for_execute_task_times_every_unit_time = time.time()
|
|
869
|
-
self._consuming_function_cost_time_total_every_unit_time = 0
|
|
870
|
-
self._execute_task_times_every_unit_time = 0
|
|
840
|
+
self.metric_calculation.cal(t_start_run_fun, current_function_result_status)
|
|
871
841
|
|
|
872
842
|
self.user_custom_record_process_info_func(current_function_result_status) # 两种方式都可以自定义,记录结果.建议使用文档4.21.b的方式继承来重写
|
|
873
843
|
await self.aio_user_custom_record_process_info_func(current_function_result_status)
|
|
@@ -954,14 +924,15 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
954
924
|
raise NotImplementedError
|
|
955
925
|
|
|
956
926
|
def check_heartbeat_and_message_count(self):
|
|
957
|
-
self.
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
927
|
+
self.metric_calculation.msg_num_in_broker = self.publisher_of_same_queue.get_message_count()
|
|
928
|
+
self.metric_calculation.last_get_msg_num_ts = time.time()
|
|
929
|
+
if time.time() - self.metric_calculation.last_timestamp_print_msg_num > 600:
|
|
930
|
+
if self.metric_calculation.msg_num_in_broker != -1:
|
|
931
|
+
self.logger.info(f'队列 [{self._queue_name}] 中还有 [{self.metric_calculation.msg_num_in_broker}] 个任务')
|
|
932
|
+
self.metric_calculation.last_timestamp_print_msg_num = time.time()
|
|
933
|
+
if self.metric_calculation.msg_num_in_broker != 0:
|
|
934
|
+
self.metric_calculation.last_timestamp_when_has_task_in_queue = time.time()
|
|
935
|
+
return self.metric_calculation.msg_num_in_broker
|
|
965
936
|
|
|
966
937
|
@abc.abstractmethod
|
|
967
938
|
def _requeue(self, kw):
|
|
@@ -999,11 +970,11 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
999
970
|
|
|
1000
971
|
def pause_consume(self):
|
|
1001
972
|
"""从远程机器可以设置队列为暂停消费状态,funboost框架会自动停止消费,此功能需要配置好redis"""
|
|
1002
|
-
RedisMixin().redis_db_frame.
|
|
973
|
+
RedisMixin().redis_db_frame.hset(RedisKeys.REDIS_KEY_PAUSE_FLAG, self.queue_name,'1')
|
|
1003
974
|
|
|
1004
975
|
def continue_consume(self):
|
|
1005
976
|
"""从远程机器可以设置队列为暂停消费状态,funboost框架会自动继续消费,此功能需要配置好redis"""
|
|
1006
|
-
RedisMixin().redis_db_frame.
|
|
977
|
+
RedisMixin().redis_db_frame.hset(RedisKeys.REDIS_KEY_PAUSE_FLAG, self.queue_name,'0')
|
|
1007
978
|
|
|
1008
979
|
@decorators.FunctionResultCacher.cached_function_result_for_a_time(120)
|
|
1009
980
|
def _judge_is_daylight(self):
|
|
@@ -1027,9 +998,9 @@ class AbstractConsumer(LoggerLevelSetterMixin, metaclass=abc.ABCMeta, ):
|
|
|
1027
998
|
no_task_time = 0
|
|
1028
999
|
while 1:
|
|
1029
1000
|
# noinspection PyBroadException
|
|
1030
|
-
message_count = self.
|
|
1001
|
+
message_count = self.metric_calculation.msg_num_in_broker
|
|
1031
1002
|
# print(message_count,self._last_execute_task_time,time.time() - self._last_execute_task_time,no_task_time)
|
|
1032
|
-
if message_count == 0 and self.
|
|
1003
|
+
if message_count == 0 and self.metric_calculation.last_execute_task_time != 0 and (time.time() - self.metric_calculation.last_execute_task_time) > minutes * 60:
|
|
1033
1004
|
no_task_time += 30
|
|
1034
1005
|
else:
|
|
1035
1006
|
no_task_time = 0
|
|
@@ -1150,6 +1121,85 @@ def wait_for_possible_has_finish_all_tasks_by_conusmer_list(consumer_list: typin
|
|
|
1150
1121
|
pool.submit(consumer.wait_for_possible_has_finish_all_tasks(minutes))
|
|
1151
1122
|
|
|
1152
1123
|
|
|
1124
|
+
class MetricCalculation:
|
|
1125
|
+
UNIT_TIME_FOR_COUNT = 10 # 这个不要随意改,需要其他地方配合,每隔多少秒计数,显示单位时间内执行多少次,暂时固定为10秒。
|
|
1126
|
+
|
|
1127
|
+
def __init__(self,conusmer:AbstractConsumer) -> None:
|
|
1128
|
+
self.consumer = conusmer
|
|
1129
|
+
|
|
1130
|
+
self.unit_time_for_count = self.UNIT_TIME_FOR_COUNT #
|
|
1131
|
+
self.execute_task_times_every_unit_time_temp = 0 # 每单位时间执行了多少次任务。
|
|
1132
|
+
self.execute_task_times_every_unit_time_temp_fail =0 # 每单位时间执行了多少次任务失败。
|
|
1133
|
+
self.current_time_for_execute_task_times_every_unit_time = time.time()
|
|
1134
|
+
self.consuming_function_cost_time_total_every_unit_time_tmp = 0
|
|
1135
|
+
self.last_execute_task_time = time.time() # 最近一次执行任务的时间。
|
|
1136
|
+
self.last_x_s_execute_count = 0
|
|
1137
|
+
self.last_x_s_execute_count_fail = 0
|
|
1138
|
+
self.last_x_s_avarage_function_spend_time = None
|
|
1139
|
+
self.last_show_remaining_execution_time = 0
|
|
1140
|
+
self.show_remaining_execution_time_interval = 300
|
|
1141
|
+
self.msg_num_in_broker = 0
|
|
1142
|
+
self.last_get_msg_num_ts = 0
|
|
1143
|
+
self.last_timestamp_when_has_task_in_queue = 0
|
|
1144
|
+
self.last_timestamp_print_msg_num = 0
|
|
1145
|
+
|
|
1146
|
+
self.total_consume_count_from_start =0
|
|
1147
|
+
self.total_consume_count_from_start_fail =0
|
|
1148
|
+
self.total_cost_time_from_start = 0 # 函数运行累计花费时间
|
|
1149
|
+
self.last_x_s_total_cost_time = None
|
|
1150
|
+
|
|
1151
|
+
def cal(self,t_start_run_fun:float,current_function_result_status:FunctionResultStatus):
|
|
1152
|
+
self.last_execute_task_time = time.time()
|
|
1153
|
+
current_msg_cost_time = time.time() - t_start_run_fun
|
|
1154
|
+
self.execute_task_times_every_unit_time_temp += 1
|
|
1155
|
+
self.total_consume_count_from_start +=1
|
|
1156
|
+
self.total_cost_time_from_start += current_msg_cost_time
|
|
1157
|
+
if current_function_result_status.success is False:
|
|
1158
|
+
self.execute_task_times_every_unit_time_temp_fail += 1
|
|
1159
|
+
self.total_consume_count_from_start_fail +=1
|
|
1160
|
+
self.consuming_function_cost_time_total_every_unit_time_tmp += current_msg_cost_time
|
|
1161
|
+
|
|
1162
|
+
if time.time() - self.current_time_for_execute_task_times_every_unit_time > self.unit_time_for_count:
|
|
1163
|
+
self.last_x_s_execute_count = self.execute_task_times_every_unit_time_temp
|
|
1164
|
+
self.last_x_s_execute_count_fail = self.execute_task_times_every_unit_time_temp_fail
|
|
1165
|
+
self.last_x_s_total_cost_time = self.consuming_function_cost_time_total_every_unit_time_tmp
|
|
1166
|
+
self.last_x_s_avarage_function_spend_time = round(self.last_x_s_total_cost_time / self.last_x_s_execute_count, 3)
|
|
1167
|
+
msg = f'{self.unit_time_for_count} 秒内执行了 {self.last_x_s_execute_count} 次函数 [ {self.consumer.consuming_function.__name__} ] ,' \
|
|
1168
|
+
f'失败了{self.last_x_s_execute_count_fail} 次,函数平均运行耗时 {self.last_x_s_avarage_function_spend_time} 秒。 '
|
|
1169
|
+
self.consumer.logger.info(msg)
|
|
1170
|
+
if time.time() - self.last_show_remaining_execution_time > self.show_remaining_execution_time_interval:
|
|
1171
|
+
self.msg_num_in_broker = self.consumer.publisher_of_same_queue.get_message_count()
|
|
1172
|
+
self.last_get_msg_num_ts = time.time()
|
|
1173
|
+
if self.msg_num_in_broker != -1: # 有的中间件无法统计或没实现统计队列剩余数量的,统一返回的是-1,不显示这句话。
|
|
1174
|
+
need_time = time_util.seconds_to_hour_minute_second(self.msg_num_in_broker / (self.execute_task_times_every_unit_time_temp / self.unit_time_for_count) /
|
|
1175
|
+
self.consumer._distributed_consumer_statistics.active_consumer_num)
|
|
1176
|
+
msg += f''' 预计还需要 {need_time} 时间 才能执行完成 队列 {self.consumer.queue_name} 中的 {self.msg_num_in_broker} 个剩余任务'''
|
|
1177
|
+
self.consumer.logger.info(msg)
|
|
1178
|
+
self.last_show_remaining_execution_time = time.time()
|
|
1179
|
+
self.current_time_for_execute_task_times_every_unit_time = time.time()
|
|
1180
|
+
self.consuming_function_cost_time_total_every_unit_time_tmp = 0
|
|
1181
|
+
self.execute_task_times_every_unit_time_temp = 0
|
|
1182
|
+
self.execute_task_times_every_unit_time_temp_fail = 0
|
|
1183
|
+
|
|
1184
|
+
def get_report_hearbeat_info(self) ->dict:
|
|
1185
|
+
return {
|
|
1186
|
+
'unit_time_for_count':self.unit_time_for_count,
|
|
1187
|
+
'last_x_s_execute_count':self.last_x_s_execute_count,
|
|
1188
|
+
'last_x_s_execute_count_fail':self.last_x_s_execute_count_fail,
|
|
1189
|
+
'last_execute_task_time':self.last_execute_task_time,
|
|
1190
|
+
'last_x_s_avarage_function_spend_time':self.last_x_s_avarage_function_spend_time,
|
|
1191
|
+
# 'last_show_remaining_execution_time':self.last_show_remaining_execution_time,
|
|
1192
|
+
'msg_num_in_broker':self.msg_num_in_broker,
|
|
1193
|
+
'current_time_for_execute_task_times_every_unit_time':self.current_time_for_execute_task_times_every_unit_time,
|
|
1194
|
+
'last_timestamp_when_has_task_in_queue':self.last_timestamp_when_has_task_in_queue,
|
|
1195
|
+
'total_consume_count_from_start':self.total_consume_count_from_start,
|
|
1196
|
+
'total_consume_count_from_start_fail':self.total_consume_count_from_start_fail,
|
|
1197
|
+
'total_cost_time_from_start':self.total_cost_time_from_start,
|
|
1198
|
+
'last_x_s_total_cost_time':self.last_x_s_total_cost_time,
|
|
1199
|
+
'avarage_function_spend_time_from_start':round(self.total_cost_time_from_start / self.total_consume_count_from_start,3) if self.total_consume_count_from_start else None,
|
|
1200
|
+
}
|
|
1201
|
+
|
|
1202
|
+
|
|
1153
1203
|
class DistributedConsumerStatistics(RedisMixin, FunboostFileLoggerMixin):
|
|
1154
1204
|
"""
|
|
1155
1205
|
为了兼容模拟mq的中间件(例如redis,他没有实现amqp协议,redis的list结构和真mq差远了),获取一个队列有几个连接活跃消费者数量。
|
|
@@ -1186,9 +1236,18 @@ class DistributedConsumerStatistics(RedisMixin, FunboostFileLoggerMixin):
|
|
|
1186
1236
|
self._server__consumer_identification_map_key_name = f'funboost_hearbeat_server__dict:{nb_log_config_default.computer_ip}'
|
|
1187
1237
|
|
|
1188
1238
|
def run(self):
|
|
1239
|
+
self._send_consumer_params()
|
|
1189
1240
|
self.send_heartbeat()
|
|
1190
1241
|
self._consumer.keep_circulating(self.SEND_HEARTBEAT_INTERVAL, block=False, daemon=False)(self.send_heartbeat)()
|
|
1191
1242
|
|
|
1243
|
+
def _send_consumer_params(self):
|
|
1244
|
+
"""
|
|
1245
|
+
保存队列的消费者参数,以便在web界面查看。
|
|
1246
|
+
:return:
|
|
1247
|
+
"""
|
|
1248
|
+
self.redis_db_frame.hmset('funboost_queue__consumer_parmas',{self._consumer.queue_name: self._consumer.consumer_params.json_str_value()})
|
|
1249
|
+
|
|
1250
|
+
|
|
1192
1251
|
def _send_heartbeat_with_dict_value(self, redis_key, ):
|
|
1193
1252
|
# 发送当前消费者进程心跳的,值是字典,按一个机器或者一个队列运行了哪些进程。
|
|
1194
1253
|
|
|
@@ -1202,10 +1261,19 @@ class DistributedConsumerStatistics(RedisMixin, FunboostFileLoggerMixin):
|
|
|
1202
1261
|
p.srem(redis_key, result)
|
|
1203
1262
|
self._consumer_identification_map['hearbeat_datetime_str'] = time_util.DatetimeConverter().datetime_str
|
|
1204
1263
|
self._consumer_identification_map['hearbeat_timestamp'] = self.timestamp()
|
|
1264
|
+
self._consumer_identification_map.update(self._consumer.metric_calculation.get_report_hearbeat_info())
|
|
1205
1265
|
value = Serialization.to_json_str(self._consumer_identification_map, )
|
|
1206
1266
|
p.sadd(redis_key, value)
|
|
1207
1267
|
p.execute()
|
|
1208
1268
|
|
|
1269
|
+
|
|
1270
|
+
def _send_msg_num(self):
|
|
1271
|
+
dic = {'msg_num_in_broker':self._consumer.metric_calculation.msg_num_in_broker,
|
|
1272
|
+
'last_get_msg_num_ts':self._consumer.metric_calculation.last_get_msg_num_ts,
|
|
1273
|
+
'report_ts':time.time(),
|
|
1274
|
+
}
|
|
1275
|
+
self.redis_db_frame.hset(RedisKeys.QUEUE__MSG_COUNT_MAP, self._consumer.queue_name, json.dumps(dic))
|
|
1276
|
+
|
|
1209
1277
|
def send_heartbeat(self):
|
|
1210
1278
|
# 根据队列名心跳的,值是字符串,方便值作为其他redis的键名
|
|
1211
1279
|
|
|
@@ -1222,6 +1290,7 @@ class DistributedConsumerStatistics(RedisMixin, FunboostFileLoggerMixin):
|
|
|
1222
1290
|
self._send_heartbeat_with_dict_value(self._server__consumer_identification_map_key_name)
|
|
1223
1291
|
self._show_active_consumer_num()
|
|
1224
1292
|
self._get_stop_and_pause_flag_from_redis()
|
|
1293
|
+
self._send_msg_num()
|
|
1225
1294
|
|
|
1226
1295
|
def _show_active_consumer_num(self):
|
|
1227
1296
|
self.active_consumer_num = self.redis_db_frame.scard(self._redis_key_name) or 1
|
|
@@ -1237,13 +1306,13 @@ class DistributedConsumerStatistics(RedisMixin, FunboostFileLoggerMixin):
|
|
|
1237
1306
|
|
|
1238
1307
|
# noinspection PyProtectedMember
|
|
1239
1308
|
def _get_stop_and_pause_flag_from_redis(self):
|
|
1240
|
-
stop_flag = self.redis_db_frame.
|
|
1309
|
+
stop_flag = self.redis_db_frame.hget(RedisKeys.REDIS_KEY_STOP_FLAG,self._consumer.queue_name)
|
|
1241
1310
|
if stop_flag is not None and int(stop_flag) == 1:
|
|
1242
1311
|
self._consumer._stop_flag = 1
|
|
1243
1312
|
else:
|
|
1244
1313
|
self._consumer._stop_flag = 0
|
|
1245
1314
|
|
|
1246
|
-
pause_flag = self.redis_db_frame.
|
|
1315
|
+
pause_flag = self.redis_db_frame.hget(RedisKeys.REDIS_KEY_PAUSE_FLAG,self._consumer.queue_name)
|
|
1247
1316
|
if pause_flag is not None and int(pause_flag) == 1:
|
|
1248
1317
|
self._consumer._pause_flag = 1
|
|
1249
1318
|
else:
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import json
|
|
2
|
+
import time
|
|
2
3
|
import typing
|
|
3
4
|
|
|
5
|
+
from pydantic import main
|
|
6
|
+
|
|
4
7
|
from funboost.utils.redis_manager import RedisMixin
|
|
5
8
|
|
|
6
9
|
from funboost.core.loggers import FunboostFileLoggerMixin,nb_log_config_default
|
|
10
|
+
from funboost.core.serialization import Serialization
|
|
11
|
+
from funboost.constant import RedisKeys
|
|
7
12
|
|
|
8
13
|
class ActiveCousumerProcessInfoGetter(RedisMixin, FunboostFileLoggerMixin):
|
|
9
14
|
"""
|
|
@@ -23,6 +28,9 @@ class ActiveCousumerProcessInfoGetter(RedisMixin, FunboostFileLoggerMixin):
|
|
|
23
28
|
result_dict = json.loads(result)
|
|
24
29
|
if self.timestamp() - result_dict['hearbeat_timestamp'] < 15:
|
|
25
30
|
active_consumers_processor_info_list.append(result_dict)
|
|
31
|
+
if self.timestamp() - result_dict['current_time_for_execute_task_times_every_unit_time'] > 30:
|
|
32
|
+
result_dict['last_x_s_execute_count'] = 0
|
|
33
|
+
result_dict['last_x_s_execute_count_fail'] = 0
|
|
26
34
|
return active_consumers_processor_info_list
|
|
27
35
|
|
|
28
36
|
def get_all_hearbeat_info_by_queue_name(self, queue_name) -> typing.List[typing.Dict]:
|
|
@@ -67,6 +75,9 @@ class ActiveCousumerProcessInfoGetter(RedisMixin, FunboostFileLoggerMixin):
|
|
|
67
75
|
info_dict = json.loads(info_str)
|
|
68
76
|
if self.timestamp() - info_dict['hearbeat_timestamp'] < 15:
|
|
69
77
|
infos_map[dict_key].append(info_dict)
|
|
78
|
+
if self.timestamp() - info_dict['current_time_for_execute_task_times_every_unit_time'] > 30:
|
|
79
|
+
info_dict['last_x_s_execute_count'] = 0
|
|
80
|
+
info_dict['last_x_s_execute_count_fail'] = 0
|
|
70
81
|
return infos_map
|
|
71
82
|
|
|
72
83
|
def get_all_hearbeat_info_partition_by_queue_name(self) -> typing.Dict[typing.AnyStr, typing.List[typing.Dict]]:
|
|
@@ -80,3 +91,72 @@ class ActiveCousumerProcessInfoGetter(RedisMixin, FunboostFileLoggerMixin):
|
|
|
80
91
|
infos_map = self._get_all_hearbeat_info_partition_by_redis_key_prefix('funboost_hearbeat_server__dict:')
|
|
81
92
|
self.logger.info(f'获取所有机器ip对应的活跃消费者进程信息,按机器ip划分,结果是 {json.dumps(infos_map, indent=4)}')
|
|
82
93
|
return infos_map
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
class QueueConusmerParamsGetter(RedisMixin, FunboostFileLoggerMixin):
|
|
98
|
+
|
|
99
|
+
def get_queue_params(self):
|
|
100
|
+
queue__consumer_params_map = self.redis_db_frame.hgetall('funboost_queue__consumer_parmas')
|
|
101
|
+
return {k:Serialization.to_dict(v) for k,v in queue__consumer_params_map.items()}
|
|
102
|
+
|
|
103
|
+
def get_pause_flag(self):
|
|
104
|
+
queue__pause_map = self.redis_db_frame.hgetall(RedisKeys.REDIS_KEY_PAUSE_FLAG)
|
|
105
|
+
return {k:int(v) for k,v in queue__pause_map.items()}
|
|
106
|
+
|
|
107
|
+
def get_msg_num(self):
|
|
108
|
+
queue__msg_count_info_map = self.redis_db_frame.hgetall(RedisKeys.QUEUE__MSG_COUNT_MAP)
|
|
109
|
+
queue__msg_count_dict = {}
|
|
110
|
+
for queue_name,info_json in queue__msg_count_info_map.items():
|
|
111
|
+
info_dict = json.loads(info_json)
|
|
112
|
+
if info_dict['report_ts'] > time.time() - 15 and info_dict['last_get_msg_num_ts'] > time.time() - 1200:
|
|
113
|
+
queue__msg_count_dict[queue_name] = info_dict['msg_num_in_broker']
|
|
114
|
+
return queue__msg_count_dict
|
|
115
|
+
|
|
116
|
+
@staticmethod
|
|
117
|
+
def _sum_filed_from_active_consumers(active_consumers:typing.List[dict],filed:str):
|
|
118
|
+
s = 0
|
|
119
|
+
for c in active_consumers:
|
|
120
|
+
# print(c)
|
|
121
|
+
if c[filed]:
|
|
122
|
+
# print(c[filed])
|
|
123
|
+
s+=c[filed]
|
|
124
|
+
return s
|
|
125
|
+
|
|
126
|
+
def get_queue_params_and_active_consumers(self):
|
|
127
|
+
queue__active_consumers_map = ActiveCousumerProcessInfoGetter().get_all_hearbeat_info_partition_by_queue_name()
|
|
128
|
+
queue__consumer_params_map = self.get_queue_params()
|
|
129
|
+
queue__pause_map = self.get_pause_flag()
|
|
130
|
+
queue__msg_count_dict = self.get_msg_num()
|
|
131
|
+
queue_params_and_active_consumers = {}
|
|
132
|
+
|
|
133
|
+
for queue, consumer_params in queue__consumer_params_map.items():
|
|
134
|
+
|
|
135
|
+
active_consumers = queue__active_consumers_map.get(queue, [])
|
|
136
|
+
# print(queue,active_consumers)
|
|
137
|
+
all_consumers_last_x_s_execute_count = self._sum_filed_from_active_consumers(active_consumers,'last_x_s_execute_count')
|
|
138
|
+
all_consumers_last_x_s_execute_count_fail = self._sum_filed_from_active_consumers(active_consumers, 'last_x_s_execute_count_fail')
|
|
139
|
+
all_consumers_last_x_s_total_cost_time = self._sum_filed_from_active_consumers(active_consumers, 'last_x_s_total_cost_time')
|
|
140
|
+
all_consumers_last_x_s_avarage_function_spend_time = round( all_consumers_last_x_s_total_cost_time / all_consumers_last_x_s_execute_count,3) if all_consumers_last_x_s_execute_count else None
|
|
141
|
+
|
|
142
|
+
all_consumers_total_consume_count_from_start = self._sum_filed_from_active_consumers(active_consumers, 'total_consume_count_from_start')
|
|
143
|
+
all_consumers_total_cost_time_from_start =self._sum_filed_from_active_consumers(active_consumers, 'total_cost_time_from_start')
|
|
144
|
+
all_consumers_avarage_function_spend_time_from_start = round(all_consumers_total_cost_time_from_start / all_consumers_total_consume_count_from_start,3) if all_consumers_total_consume_count_from_start else None
|
|
145
|
+
|
|
146
|
+
queue_params_and_active_consumers[queue] = {
|
|
147
|
+
'queue_params':consumer_params,
|
|
148
|
+
'active_consumers':active_consumers,
|
|
149
|
+
'pause_flag':queue__pause_map.get(queue,-1),
|
|
150
|
+
'msg_num_in_broker':queue__msg_count_dict.get(queue,None),
|
|
151
|
+
'all_consumers_last_x_s_execute_count':all_consumers_last_x_s_execute_count,
|
|
152
|
+
'all_consumers_last_x_s_execute_count_fail':all_consumers_last_x_s_execute_count_fail,
|
|
153
|
+
'all_consumers_last_x_s_avarage_function_spend_time':all_consumers_last_x_s_avarage_function_spend_time,
|
|
154
|
+
'all_consumers_avarage_function_spend_time_from_start':all_consumers_avarage_function_spend_time_from_start,
|
|
155
|
+
'all_consumers_total_consume_count_from_start':self._sum_filed_from_active_consumers(active_consumers, 'total_consume_count_from_start'),
|
|
156
|
+
'all_consumers_total_consume_count_from_start_fail':self._sum_filed_from_active_consumers(active_consumers, 'total_consume_count_from_start_fail'),
|
|
157
|
+
}
|
|
158
|
+
return queue_params_and_active_consumers
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
if __name__ == '__main__':
|
|
162
|
+
print(Serialization.to_json_str(QueueConusmerParamsGetter().get_queue_params_and_active_consumers()))
|
|
@@ -87,7 +87,7 @@ class FunctionResultStatus():
|
|
|
87
87
|
'insert_minutes': datetime_str[:-3],
|
|
88
88
|
})
|
|
89
89
|
if not without_datetime_obj:
|
|
90
|
-
item.update({'insert_time':
|
|
90
|
+
item.update({'insert_time': time_util.DatetimeConverter().datetime_obj,
|
|
91
91
|
'utime': datetime.datetime.utcnow(),
|
|
92
92
|
})
|
|
93
93
|
else:
|
|
Binary file
|
|
Binary file
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
# @Author : ydf
|
|
3
3
|
# @Time : 2022/9/18 0018 14:46
|
|
4
|
+
import sys
|
|
5
|
+
print(sys.path)
|
|
6
|
+
|
|
7
|
+
import os
|
|
8
|
+
print("PYTHONPATH:", os.environ.get('PYTHONPATH'))
|
|
9
|
+
|
|
4
10
|
|
|
5
11
|
import datetime
|
|
6
12
|
import json
|
|
@@ -16,8 +22,10 @@ from wtforms.validators import DataRequired, Length
|
|
|
16
22
|
from flask_login import login_user, logout_user, login_required, LoginManager, UserMixin
|
|
17
23
|
|
|
18
24
|
import nb_log
|
|
19
|
-
from funboost import nb_print
|
|
25
|
+
from funboost import nb_print,ActiveCousumerProcessInfoGetter,BoostersManager,PublisherParams,RedisMixin
|
|
20
26
|
from funboost.function_result_web.functions import get_cols, query_result, get_speed, Statistic
|
|
27
|
+
from funboost.core.active_cousumer_info_getter import QueueConusmerParamsGetter
|
|
28
|
+
from funboost.constant import RedisKeys
|
|
21
29
|
|
|
22
30
|
app = Flask(__name__)
|
|
23
31
|
app.secret_key = 'mtfy54321'
|
|
@@ -70,11 +78,11 @@ def login():
|
|
|
70
78
|
form = LoginForm()
|
|
71
79
|
if request.method == 'POST':
|
|
72
80
|
|
|
73
|
-
nb_print(form.validate())
|
|
74
|
-
nb_print(form.password.data)
|
|
75
|
-
nb_print(form.user_name.data)
|
|
76
|
-
nb_print(form.user_name.errors)
|
|
77
|
-
nb_print(form.password.errors)
|
|
81
|
+
# nb_print(form.validate())
|
|
82
|
+
# nb_print(form.password.data)
|
|
83
|
+
# nb_print(form.user_name.data)
|
|
84
|
+
# nb_print(form.user_name.errors)
|
|
85
|
+
# nb_print(form.password.errors)
|
|
78
86
|
if form.validate_on_submit():
|
|
79
87
|
user = query_user(form.user_name.data)
|
|
80
88
|
if user is not None and request.form['password'] == user['password']:
|
|
@@ -139,13 +147,102 @@ def speed_statistic_for_echarts():
|
|
|
139
147
|
stat.build_result()
|
|
140
148
|
return jsonify(stat.result)
|
|
141
149
|
|
|
150
|
+
@app.route('/tpl/<template>')
|
|
151
|
+
@login_required
|
|
152
|
+
def serve_template(template):
|
|
153
|
+
# 安全检查:确保只能访问templates目录下的html文件
|
|
154
|
+
if not template.endswith('.html'):
|
|
155
|
+
return 'Invalid request', 400
|
|
156
|
+
try:
|
|
157
|
+
return render_template(template)
|
|
158
|
+
except Exception as e:
|
|
159
|
+
return f'Template not found: {template}', 404
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
@app.route('/running_consumer/hearbeat_info_by_queue_name')
|
|
163
|
+
def hearbeat_info_by_queue_name():
|
|
164
|
+
if request.args.get('queue_name') in ('所有',None):
|
|
165
|
+
info_map = ActiveCousumerProcessInfoGetter().get_all_hearbeat_info_partition_by_queue_name()
|
|
166
|
+
ret_list = []
|
|
167
|
+
for queue_name,dic in info_map.items():
|
|
168
|
+
ret_list.extend(dic)
|
|
169
|
+
return jsonify(ret_list)
|
|
170
|
+
else:
|
|
171
|
+
return jsonify(ActiveCousumerProcessInfoGetter().get_all_hearbeat_info_by_queue_name(request.args.get('queue_name')))
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
@app.route('/running_consumer/hearbeat_info_by_ip')
|
|
176
|
+
def hearbeat_info_by_ip():
|
|
177
|
+
if request.args.get('ip') in ('所有',None):
|
|
178
|
+
info_map = ActiveCousumerProcessInfoGetter().get_all_hearbeat_info_partition_by_ip()
|
|
179
|
+
ret_list = []
|
|
180
|
+
for queue_name,dic in info_map.items():
|
|
181
|
+
ret_list.extend(dic)
|
|
182
|
+
return jsonify(ret_list)
|
|
183
|
+
else:
|
|
184
|
+
return jsonify(ActiveCousumerProcessInfoGetter().get_all_hearbeat_info_by_ip(request.args.get('ip')))
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
@app.route('/running_consumer/hearbeat_info_partion_by_queue_name')
|
|
188
|
+
def hearbeat_info_partion_by_queue_name():
|
|
189
|
+
info_map = ActiveCousumerProcessInfoGetter().get_all_hearbeat_info_partition_by_queue_name()
|
|
190
|
+
ret_list = []
|
|
191
|
+
total_count = 0
|
|
192
|
+
for k,v in info_map.items():
|
|
193
|
+
ret_list.append({'collection_name':k,'count':len(v)})
|
|
194
|
+
total_count +=len(v)
|
|
195
|
+
ret_list = sorted(ret_list, key=lambda x: x['collection_name'])
|
|
196
|
+
ret_list.insert(0,{'collection_name':'所有','count':total_count})
|
|
197
|
+
return jsonify(ret_list)
|
|
198
|
+
|
|
199
|
+
@app.route('/running_consumer/hearbeat_info_partion_by_ip')
|
|
200
|
+
def hearbeat_info_partion_by_ip():
|
|
201
|
+
info_map = ActiveCousumerProcessInfoGetter().get_all_hearbeat_info_partition_by_ip()
|
|
202
|
+
ret_list = []
|
|
203
|
+
total_count = 0
|
|
204
|
+
for k,v in info_map.items():
|
|
205
|
+
ret_list.append({'collection_name':k,'count':len(v)})
|
|
206
|
+
total_count +=len(v)
|
|
207
|
+
ret_list = sorted(ret_list, key=lambda x: x['collection_name'])
|
|
208
|
+
ret_list.insert(0,{'collection_name':'所有','count':total_count})
|
|
209
|
+
print(ret_list)
|
|
210
|
+
return jsonify(ret_list)
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
@app.route('/queue/params_and_active_consumers')
|
|
214
|
+
def get_queue_params_and_active_consumers():
|
|
215
|
+
return jsonify(QueueConusmerParamsGetter().get_queue_params_and_active_consumers())
|
|
216
|
+
|
|
217
|
+
@app.route('/queue/message_count/<broker_kind>/<queue_name>')
|
|
218
|
+
def get_message_count(broker_kind,queue_name):
|
|
219
|
+
publisher = BoostersManager.get_cross_project_publisher(PublisherParams(queue_name=queue_name, broker_kind=broker_kind, publish_msg_log_use_full_msg=True))
|
|
220
|
+
return jsonify({'count':publisher.get_message_count(),'success':True})
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
@app.route('/queue/clear/<broker_kind>/<queue_name>',methods=['POST'])
|
|
224
|
+
def clear_queue(broker_kind,queue_name):
|
|
225
|
+
publisher = BoostersManager.get_cross_project_publisher(PublisherParams(queue_name=queue_name, broker_kind=broker_kind, publish_msg_log_use_full_msg=True))
|
|
226
|
+
publisher.clear()
|
|
227
|
+
return jsonify({'success':True})
|
|
228
|
+
|
|
229
|
+
@app.route('/queue/pause/<queue_name>', methods=['POST'])
|
|
230
|
+
def pause_cousume(queue_name):
|
|
231
|
+
RedisMixin().redis_db_frame.hset(RedisKeys.REDIS_KEY_PAUSE_FLAG, queue_name,'1')
|
|
232
|
+
return jsonify({'success':True})
|
|
233
|
+
|
|
234
|
+
@app.route('/queue/resume/<queue_name>',methods=['POST'])
|
|
235
|
+
def resume_consume(queue_name):
|
|
236
|
+
RedisMixin().redis_db_frame.hset(RedisKeys.REDIS_KEY_PAUSE_FLAG, queue_name,'0')
|
|
237
|
+
return jsonify({'success':True})
|
|
238
|
+
|
|
142
239
|
|
|
143
240
|
if __name__ == '__main__':
|
|
144
241
|
# app.jinja_env.auto_reload = True
|
|
145
242
|
# with app.test_request_context():
|
|
146
243
|
# print(url_for('query_cols_view'))
|
|
147
244
|
|
|
148
|
-
app.run(debug=False, threaded=True, host='0.0.0.0', port=
|
|
245
|
+
app.run(debug=False, threaded=True, host='0.0.0.0', port=27018)
|
|
149
246
|
|
|
150
247
|
'''
|
|
151
248
|
linux 是export , win是 set
|
|
@@ -93,8 +93,21 @@ class Statistic(LoggerMixin):
|
|
|
93
93
|
'recent_60_seconds': {'time_arr': [], 'count_arr': []}}
|
|
94
94
|
|
|
95
95
|
def statistic_by_period(self, t_start: str, t_end: str):
|
|
96
|
-
|
|
97
|
-
'$lt': time_util.DatetimeConverter(t_end).datetime_obj}}
|
|
96
|
+
condition = {'insert_time': {'$gt': time_util.DatetimeConverter(t_start).datetime_obj,
|
|
97
|
+
'$lt': time_util.DatetimeConverter(t_end).datetime_obj}}
|
|
98
|
+
|
|
99
|
+
# now = datetime.datetime.now()
|
|
100
|
+
# start_time = now - datetime.timedelta(hours=1)
|
|
101
|
+
# end_time = now
|
|
102
|
+
# condition = {
|
|
103
|
+
# 'insert_time': {
|
|
104
|
+
# '$gt': start_time,
|
|
105
|
+
# '$lt': end_time
|
|
106
|
+
# }
|
|
107
|
+
# }
|
|
108
|
+
count = self.col.count_documents(condition)
|
|
109
|
+
print(count,t_start,t_end,time_util.DatetimeConverter(t_start).datetime_obj.timestamp(),condition)
|
|
110
|
+
return count
|
|
98
111
|
|
|
99
112
|
def build_result(self):
|
|
100
113
|
with decorators.TimerContextManager():
|
|
@@ -133,12 +146,12 @@ class Statistic(LoggerMixin):
|
|
|
133
146
|
|
|
134
147
|
|
|
135
148
|
if __name__ == '__main__':
|
|
136
|
-
print(get_cols('4'))
|
|
149
|
+
# print(get_cols('4'))
|
|
137
150
|
# pprint(query_result('queue_test54_task_status', '2019-09-15 00:00:00', '2019-09-25 00:00:00', True, '999', 0))
|
|
138
151
|
# print(json.dumps(query_result(**{'col_name': 'queue_test56', 'start_time': '2019-09-18 16:03:29', 'end_time': '2019-09-21 16:03:29', 'is_success': '1', 'function_params': '', 'page': '0'}))[:1000])
|
|
139
152
|
# nb_print(get_speed_last_minute('queue_test54'))
|
|
140
153
|
|
|
141
154
|
# nb_print(get_speed('queue_test56', '2019-09-18 16:03:29', '2019-09-23 16:03:29'))
|
|
142
|
-
stat = Statistic('
|
|
155
|
+
stat = Statistic('queue_test_f01t')
|
|
143
156
|
stat.build_result()
|
|
144
157
|
nb_print(stat.result)
|