pytbox 0.1.5__py3-none-any.whl → 0.1.7__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.
pytbox/alert/ping.py CHANGED
@@ -1,6 +1,5 @@
1
1
  #!/usr/bin/env python3
2
2
 
3
-
4
3
  from ..database.victoriametrics import VictoriaMetrics
5
4
  from ..lib.load_config import load_config
6
5
 
pytbox/alicloud/sls.py CHANGED
@@ -5,19 +5,21 @@ from typing import Literal
5
5
  from aliyun.log import GetLogsRequest, LogItem, PutLogsRequest
6
6
  from aliyun.log import LogClient as SlsLogClient
7
7
  from aliyun.log.auth import AUTH_VERSION_4
8
- from ..utils.env import check_env
9
8
 
10
9
 
11
10
 
12
11
  class AliCloudSls:
13
-
14
- def __init__(self, access_key_id: str=None, access_key_secret: str=None, project: str, logstore: str):
12
+ '''
13
+ pip install -U aliyun-log-python-sdk
14
+ '''
15
+ def __init__(self, access_key_id: str=None, access_key_secret: str=None, project: str=None, logstore: str=None, env: str='prod'):
15
16
  # 日志服务的服务接入点
16
17
  self.endpoint = "cn-shanghai.log.aliyuncs.com"
17
18
  # 创建 LogClient 实例,使用 V4 签名,根据实际情况填写 region,这里以杭州为例
18
19
  self.client = SlsLogClient(self.endpoint, access_key_id, access_key_secret, auth_version=AUTH_VERSION_4, region='cn-shanghai')
19
20
  self.project = project
20
21
  self.logstore = logstore
22
+ self.env = env
21
23
 
22
24
  def get_logs(self, project_name, logstore_name, query, from_time, to_time):
23
25
  logstore_index = {'line': {
@@ -57,7 +59,7 @@ class AliCloudSls:
57
59
  log_group = []
58
60
  log_item = LogItem()
59
61
  contents = [
60
- ('env', check_env()),
62
+ ('env', self.env),
61
63
  ('level', level),
62
64
  ('app', app),
63
65
  ('msg', msg),
@@ -69,8 +71,9 @@ class AliCloudSls:
69
71
  log_item.set_contents(contents)
70
72
  log_group.append(log_item)
71
73
  request = PutLogsRequest(self.project, self.logstore, topic, "", log_group, compress=False)
72
- self.client.put_logs(request)
73
-
74
+ r = self.client.put_logs(request)
75
+ return r
76
+
74
77
  def put_logs_for_meraki(self, alert):
75
78
  log_group = []
76
79
  log_item = LogItem()
pytbox/base.py CHANGED
@@ -15,6 +15,9 @@ from pytbox.vmware import VMwareClient
15
15
  from pytbox.pyjira import PyJira
16
16
  from pytbox.mail.client import MailClient
17
17
  from pytbox.mail.alimail import AliMail
18
+ from pytbox.alicloud.sls import AliCloudSls
19
+ from pytbox.utils.cronjob import cronjob_counter
20
+
18
21
 
19
22
  config = load_config_by_file(path='/workspaces/pytbox/tests/alert/config_dev.toml', oc_vault_id=os.environ.get('oc_vault_id'))
20
23
 
@@ -53,6 +56,19 @@ def get_logger(app):
53
56
  mongo=get_mongo('alert_program')
54
57
  )
55
58
 
59
+ def get_logger_sls(app):
60
+ return AppLogger(
61
+ app_name=app,
62
+ enable_sls=True,
63
+ feishu=feishu,
64
+ dida=dida,
65
+ mongo=get_mongo('alert_program'),
66
+ sls_access_key_id=config['alicloud']['account1']['access_key_id'],
67
+ sls_access_key_secret=config['alicloud']['account1']['access_key_secret'],
68
+ sls_project=config['alicloud']['account1']['project'],
69
+ sls_logstore=config['alicloud']['account1']['logstore']
70
+ )
71
+
56
72
  # ad_dev = ADClient(
57
73
  # server=config['ad']['dev']['AD_SERVER'],
58
74
  # base_dn=config['ad']['dev']['BASE_DN'],
@@ -85,4 +101,15 @@ pyjira = PyJira(
85
101
 
86
102
  mail_163 = MailClient(mail_address=config['mail']['163']['mail_address'], password=config['mail']['163']['password'])
87
103
  mail_qq = MailClient(mail_address=config['mail']['qq']['mail_address'], password=config['mail']['qq']['password'])
88
- ali_mail = AliMail(mail_address=config['mail']['aliyun']['mail_address'], client_id=config['mail']['aliyun']['client_id'], client_secret=config['mail']['aliyun']['client_secret'])
104
+ ali_mail = AliMail(mail_address=config['mail']['aliyun']['mail_address'], client_id=config['mail']['aliyun']['client_id'], client_secret=config['mail']['aliyun']['client_secret'])
105
+
106
+ sls = AliCloudSls(
107
+ access_key_id=config['alicloud']['account1']['access_key_id'],
108
+ access_key_secret=config['alicloud']['account1']['access_key_secret'],
109
+ project=config['alicloud']['account1']['project'],
110
+ logstore=config['alicloud']['account1']['logstore']
111
+ )
112
+
113
+
114
+ def get_cronjob_counter(app_type='', app='', comment=None, schedule_interval=None, schedule_cron=None):
115
+ return cronjob_counter(vm=vm, log=get_logger('cronjob_counter'), app_type=app_type, app=app, comment=comment, schedule_interval=schedule_interval, schedule_cron=schedule_cron)
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env python3
2
2
 
3
+ import time
3
4
  import json
4
- from typing import Literal, Optional
5
+ from typing import Literal, Optional, Dict, List
5
6
  import requests
6
7
  from ..utils.response import ReturnResponse
7
8
  from ..utils.load_vm_devfile import load_dev_file
@@ -9,7 +10,7 @@ from ..utils.load_vm_devfile import load_dev_file
9
10
 
10
11
  class VictoriaMetrics:
11
12
 
12
- def __init__(self, url: str='', timeout: int=3) -> None:
13
+ def __init__(self, url: str='', timeout: int=3, env: str='prod') -> None:
13
14
  self.url = url
14
15
  self.timeout = timeout
15
16
  self.session = requests.Session()
@@ -17,8 +18,45 @@ class VictoriaMetrics:
17
18
  'Content-Type': 'application/json',
18
19
  'Accept': 'application/json'
19
20
  })
21
+ self.env = env
22
+
23
+ def insert(self, metric_name: str = '', labels: Dict[str, str] = None,
24
+ value: List[float] = None, timestamp: int = None) -> ReturnResponse:
25
+ """插入指标数据。
20
26
 
21
- def query(self, query: str, output_format: Literal['json']=None) -> ReturnResponse:
27
+ Args:
28
+ metric_name: 指标名称
29
+ labels: 标签字典
30
+ value: 值列表
31
+ timestamp: 时间戳(毫秒),默认为当前时间
32
+
33
+ Raises:
34
+ requests.RequestException: 当请求失败时抛出
35
+ """
36
+ if labels is None:
37
+ labels = {}
38
+ if value is None:
39
+ value = 1
40
+ if timestamp is None:
41
+ timestamp = int(time.time() * 1000)
42
+
43
+ url = f"{self.url}/api/v1/import"
44
+ data = {
45
+ "metric": {
46
+ "__name__": metric_name,
47
+ **labels
48
+ },
49
+ "values": [value],
50
+ "timestamps": [timestamp]
51
+ }
52
+
53
+ try:
54
+ response = requests.post(url, json=data, timeout=self.timeout)
55
+ return ReturnResponse(code=0, msg=f"数据插入成功,状态码: {response.status_code}, metric_name: {metric_name}, labels: {labels}, value: {value}, timestamp: {timestamp}")
56
+ except requests.RequestException as e:
57
+ return ReturnResponse(code=1, msg=f"数据插入失败: {e}")
58
+
59
+ def query(self, query: str=None, output_format: Literal['json']=None) -> ReturnResponse:
22
60
  '''
23
61
  查询指标数据
24
62
 
@@ -61,6 +99,52 @@ class VictoriaMetrics:
61
99
  else:
62
100
  return resp
63
101
 
102
+ def query_range(self, query):
103
+ '''
104
+ 查询指标数据
105
+
106
+ Args:
107
+ query (str): 查询语句
108
+
109
+ Returns:
110
+ dict: 查询结果
111
+ '''
112
+ url = f"{self.url}/prometheus/api/v1/query_range"
113
+
114
+ data = {
115
+ 'query': query,
116
+ 'start': '-1d',
117
+ 'step': '1h'
118
+ }
119
+
120
+ r = requests.post(url, data=data, timeout=self.timeout)
121
+ res_json = r.json()
122
+ print(res_json)
123
+ # status = res_json.get("status")
124
+ # result = res_json.get("data", {}).get("result", [])
125
+ # is_json = output_format == 'json'
126
+
127
+ # if status == "success":
128
+ # if result:
129
+ # code = 0
130
+ # msg = f"[{query}] 查询成功!"
131
+ # data = result
132
+ # else:
133
+ # code = 2
134
+ # msg = f"[{query}] 没有查询到结果"
135
+ # data = res_json
136
+ # else:
137
+ # code = 1
138
+ # msg = f"[{query}] 查询失败: {res_json.get('error')}"
139
+ # data = res_json
140
+
141
+ # resp = ReturnResponse(code=code, msg=msg, data=data)
142
+
143
+ # if is_json:
144
+ # json_result = json.dumps(resp.__dict__, ensure_ascii=False)
145
+ # return json_result
146
+ # else:
147
+ # return resp
64
148
  def get_labels(self, metric_name: str) -> ReturnResponse:
65
149
  url = f"{self.url}/api/v1/series?match[]={metric_name}"
66
150
  response = requests.get(url, timeout=self.timeout)
@@ -104,7 +188,6 @@ class VictoriaMetrics:
104
188
  code = 0
105
189
  msg = f"已检查 {target} 最近 {last_minute} 分钟是正常的!"
106
190
  else:
107
-
108
191
  if all(str(item[1]) == "1" for item in values):
109
192
  code = 1
110
193
  msg = f"已检查 {target} 最近 {last_minute} 分钟是异常的!"
@@ -114,7 +197,6 @@ class VictoriaMetrics:
114
197
  elif r.code == 2:
115
198
  code = 2
116
199
  msg = f"没有查询到 {target} 最近 {last_minute} 分钟的ping结果!"
117
-
118
200
  try:
119
201
  data = r.data[0]
120
202
  except KeyError:
@@ -146,4 +228,85 @@ class VictoriaMetrics:
146
228
  query = f'(rate(snmp_interface_ifHCOutOctets{{sysName="{sysName}", ifName="{ifName}"}}[{last_minutes}m])) * 8 / 1000000'
147
229
  r = self.query(query)
148
230
  rate = r.data[0]['value'][1]
149
- return int(float(rate))
231
+ return int(float(rate))
232
+
233
+ def check_snmp_port_status(self, sysname: str=None, if_name: str=None, last_minute: int=5) -> ReturnResponse:
234
+ '''
235
+ 查询端口状态
236
+ status code 可参考 SNMP 文件 https://mibbrowser.online/mibdb_search.php?mib=IF-MIB
237
+
238
+ Args:
239
+ sysname (_type_): 设备名称
240
+ if_name (_type_): _description_
241
+ last_minute (_type_): _description_
242
+
243
+ Returns:
244
+ ReturnResponse:
245
+ code: 0, msg: , data: up,down
246
+ '''
247
+ q = f"""avg_over_time(snmp_interface_ifOperStatus{{sysName="{sysname}", ifName="{if_name}"}}[{last_minute}m])"""
248
+ r = self.query(query=q)
249
+ if r.code == 0:
250
+ status_code = r.data[0]['value'][1]
251
+ if status_code == 1:
252
+ status = 'up'
253
+ else:
254
+ status = 'down'
255
+ return ReturnResponse(code=0, msg=f"{sysname} {if_name} 最近 {last_minute} 分钟端口状态为 {status}", data=status)
256
+ else:
257
+ return r
258
+
259
+ def insert_cronjob_run_status(self,
260
+ app_type: Literal['alert', 'meraki', 'other']='other',
261
+ app: str='',
262
+ status_code: Literal[0, 1]=1,
263
+ comment: str=None,
264
+ schedule_interval: str=None,
265
+ schedule_cron: str=None
266
+ ) -> ReturnResponse:
267
+ labels = {
268
+ "app": app,
269
+ "env": self.env,
270
+ }
271
+ if app_type:
272
+ labels['app_type'] = app_type
273
+ if comment:
274
+ labels['comment'] = comment
275
+
276
+ if schedule_interval:
277
+ labels['schedule_type'] = 'interval'
278
+ labels['schedule_interval'] = schedule_interval
279
+
280
+ if schedule_cron:
281
+ labels['schedule_type'] = 'cron'
282
+ labels['schedule_cron'] = schedule_cron
283
+
284
+ r = self.insert(metric_name="cronjob_run_status", labels=labels, value=status_code)
285
+ return r
286
+
287
+ def insert_cronjob_duration_seconds(self,
288
+ app_type: Literal['alert', 'meraki', 'other']='other',
289
+ app: str='',
290
+ duration_seconds: float=None,
291
+ comment: str=None,
292
+ schedule_interval: str=None,
293
+ schedule_cron: str=None
294
+ ) -> ReturnResponse:
295
+ labels = {
296
+ "app": app,
297
+ "env": self.env
298
+ }
299
+ if app_type:
300
+ labels['app_type'] = app_type
301
+ if comment:
302
+ labels['comment'] = comment
303
+
304
+ if schedule_interval:
305
+ labels['schedule_type'] = 'interval'
306
+ labels['schedule_interval'] = schedule_interval
307
+
308
+ if schedule_cron:
309
+ labels['schedule_type'] = 'cron'
310
+ labels['schedule_cron'] = schedule_cron
311
+ r = self.insert(metric_name="cronjob_run_duration_seconds", labels=labels, value=duration_seconds)
312
+ return r
pytbox/log/logger.py CHANGED
@@ -9,7 +9,7 @@ from ..database.mongo import Mongo
9
9
  from ..feishu.client import Client as FeishuClient
10
10
  from ..utils.timeutils import TimeUtils
11
11
  from ..dida365 import Dida365
12
-
12
+ from ..alicloud.sls import AliCloudSls
13
13
 
14
14
  logger.remove()
15
15
  logger.add(sys.stdout, colorize=True, format="<green>{time:YYYY-MM-DD HH:mm:ss.SSS}</green> | <level>{level: <8}</level> | <level>{message}</level>")
@@ -31,7 +31,6 @@ class AppLogger:
31
31
  feishu: FeishuClient=None,
32
32
  dida: Dida365=None,
33
33
  enable_sls: bool=False,
34
- sls_url: str=None,
35
34
  sls_access_key_id: str=None,
36
35
  sls_access_key_secret: str=None,
37
36
  sls_project: str=None,
@@ -49,10 +48,17 @@ class AppLogger:
49
48
  self.stream = stream
50
49
  self.victorialog = Victorialog(url=victorialog_url)
51
50
  self.enable_victorialog = enable_victorialog
51
+ self.enable_sls = enable_sls
52
52
  self.mongo = mongo
53
53
  self.feishu = feishu
54
54
  self.dida = dida
55
-
55
+ self.sls = AliCloudSls(
56
+ access_key_id=sls_access_key_id,
57
+ access_key_secret=sls_access_key_secret,
58
+ project=sls_project,
59
+ logstore=sls_logstore
60
+ )
61
+
56
62
  def _get_caller_info(self) -> tuple[str, int, str]:
57
63
  """
58
64
  获取调用者信息
@@ -78,6 +84,9 @@ class AppLogger:
78
84
  logger.debug(f"[{caller_filename}:{caller_lineno}:{caller_function}] {message}")
79
85
  if self.enable_victorialog:
80
86
  self.victorialog.send_program_log(stream=self.stream, level="DEBUG", message=message, app_name=self.app_name, file_name=call_full_filename, line_number=caller_lineno, function_name=caller_function)
87
+ if self.enable_sls:
88
+ self.sls.put_logs(level="DEBUG", msg=message, app=self.app_name, caller_filename=caller_filename, caller_lineno=caller_lineno, caller_function=caller_function, call_full_filename=call_full_filename)
89
+
81
90
 
82
91
  def info(self, message: str='', feishu_notify: bool=False):
83
92
  """记录信息级别日志"""
@@ -85,22 +94,28 @@ class AppLogger:
85
94
  logger.info(f"[{caller_filename}:{caller_lineno}:{caller_function}] {message}")
86
95
  if self.enable_victorialog:
87
96
  r = self.victorialog.send_program_log(stream=self.stream, level="INFO", message=message, app_name=self.app_name, file_name=call_full_filename, line_number=caller_lineno, function_name=caller_function)
97
+ if self.enable_sls:
98
+ self.sls.put_logs(level="INFO", msg=message, app=self.app_name, caller_filename=caller_filename, caller_lineno=caller_lineno, caller_function=caller_function, call_full_filename=call_full_filename)
88
99
  if feishu_notify:
89
100
  self.feishu(message)
90
-
101
+
91
102
  def warning(self, message: str):
92
103
  """记录警告级别日志"""
93
104
  caller_filename, caller_lineno, caller_function, call_full_filename = self._get_caller_info()
94
105
  logger.warning(f"[{caller_filename}:{caller_lineno}:{caller_function}] {message}")
95
106
  if self.enable_victorialog:
96
107
  self.victorialog.send_program_log(stream=self.stream, level="WARN", message=message, app_name=self.app_name, file_name=call_full_filename, line_number=caller_lineno, function_name=caller_function)
97
-
108
+ if self.enable_sls:
109
+ self.sls.put_logs(level="WARN", msg=message, app=self.app_name, caller_filename=caller_filename, caller_lineno=caller_lineno, caller_function=caller_function, call_full_filename=call_full_filename)
110
+
98
111
  def error(self, message: str):
99
112
  """记录错误级别日志"""
100
113
  caller_filename, caller_lineno, caller_function, call_full_filename = self._get_caller_info()
101
114
  logger.error(f"[{caller_filename}:{caller_lineno}:{caller_function}] {message}")
102
115
  if self.enable_victorialog:
103
116
  self.victorialog.send_program_log(stream=self.stream, level="ERROR", message=message, app_name=self.app_name, file_name=call_full_filename, line_number=caller_lineno, function_name=caller_function)
117
+ if self.enable_sls:
118
+ self.sls.put_logs(level="ERROR", msg=message, app=self.app_name, caller_filename=caller_filename, caller_lineno=caller_lineno, caller_function=caller_function, call_full_filename=call_full_filename)
104
119
 
105
120
  if self.feishu:
106
121
  existing_message = self.mongo.collection.find_one({"message": message}, sort=[("time", -1)])
@@ -150,7 +165,8 @@ class AppLogger:
150
165
  logger.critical(f"[{caller_filename}:{caller_lineno}:{caller_function}] {message}")
151
166
  if self.enable_victorialog:
152
167
  self.victorialog.send_program_log(stream=self.stream, level="CRITICAL", message=message, app_name=self.app_name, file_name=call_full_filename, line_number=caller_lineno, function_name=caller_function)
153
-
168
+ if self.enable_sls:
169
+ self.sls.put_logs(level="CRITICAL", msg=message, app=self.app_name, caller_filename=caller_filename, caller_lineno=caller_lineno, caller_function=caller_function, call_full_filename=call_full_filename)
154
170
 
155
171
  # 使用示例
156
172
  if __name__ == "__main__":
@@ -0,0 +1,79 @@
1
+ #!/usr/bin/env python3
2
+
3
+ import time
4
+ from functools import wraps
5
+ from typing import Literal
6
+ from ..database.victoriametrics import VictoriaMetrics
7
+
8
+
9
+ def cronjob_counter(vm: VictoriaMetrics=None, log: str=None, app_type: Literal['']='', app='', comment=None, schedule_interval=None, schedule_cron=None):
10
+ """计算函数运行时间的装饰器,支持记录到 VictoriaMetrics
11
+
12
+ Args:
13
+ app_type: 应用类型 ('alert', 'meraki', 'other')
14
+ app: 应用名称
15
+ comment: 备注信息
16
+ schedule_interval: 定时任务间隔(如 '1m', '5m')
17
+ schedule_cron: cron 表达式(如 '0 */5 * * *')
18
+ """
19
+ def decorator(func):
20
+ @wraps(func)
21
+ def wrapper(*args, **kwargs):
22
+ start_time = time.time()
23
+
24
+ try:
25
+ result = func(*args, **kwargs)
26
+ end_time = time.time()
27
+ elapsed_time = end_time - start_time
28
+
29
+ # 记录任务成功完成状态
30
+ vm.insert_cronjob_run_status(
31
+ app_type=app_type,
32
+ app=app,
33
+ status_code=1, # 0 表示成功完成
34
+ comment=f"成功完成: {comment}" if comment else "任务成功完成",
35
+ schedule_interval=schedule_interval,
36
+ schedule_cron=schedule_cron
37
+ )
38
+
39
+ # 记录执行耗时
40
+ vm.insert_cronjob_duration_seconds(
41
+ app_type=app_type,
42
+ app=app,
43
+ duration_seconds=elapsed_time,
44
+ comment=comment,
45
+ schedule_interval=schedule_interval,
46
+ schedule_cron=schedule_cron
47
+ )
48
+ log.info(f"{app} 任务成功完成, 耗时 {elapsed_time:.2f} 秒")
49
+
50
+ return result
51
+
52
+ except Exception as e:
53
+ end_time = time.time()
54
+ elapsed_time = end_time - start_time
55
+
56
+ # 记录任务失败状态
57
+ error_comment = f"执行出错: {str(e)}" if not comment else f"{comment} (出错: {str(e)})"
58
+ vm.insert_cronjob_run_status(
59
+ app_type=app_type,
60
+ app=app,
61
+ status_code=0, # 1 表示失败
62
+ comment=error_comment,
63
+ schedule_interval=schedule_interval,
64
+ schedule_cron=schedule_cron
65
+ )
66
+
67
+ # 即使出错也记录耗时
68
+ vm.insert_cronjob_duration_seconds(
69
+ app_type=app_type,
70
+ app=app,
71
+ duration_seconds=elapsed_time,
72
+ comment=error_comment,
73
+ schedule_interval=schedule_interval,
74
+ schedule_cron=schedule_cron
75
+ )
76
+ log.error(f"任务失败: {error_comment}")
77
+ raise
78
+ return wrapper
79
+ return decorator
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pytbox
3
- Version: 0.1.5
3
+ Version: 0.1.7
4
4
  Summary: A collection of Python integrations and utilities (Feishu, Dida365, VictoriaMetrics, ...)
5
5
  Author-email: mingming hou <houm01@foxmail.com>
6
6
  License-Expression: MIT
@@ -1,4 +1,4 @@
1
- pytbox/base.py,sha256=wWjzJ6gcEnUBIG3-U49CKeoqT-1Tk20EJRt2oYDAj0k,3157
1
+ pytbox/base.py,sha256=uzrv0vlHVPOr2JjpUGd8R2Wr-iRf6SysnrAYOalKXYY,4283
2
2
  pytbox/cli.py,sha256=N775a0GK80IT2lQC2KRYtkZpIiu9UjavZmaxgNUgJhQ,160
3
3
  pytbox/dida365.py,sha256=pUMPB9AyLZpTTbaz2LbtzdEpyjvuGf4YlRrCvM5sbJo,10545
4
4
  pytbox/excel.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -7,8 +7,8 @@ pytbox/onepassword_sa.py,sha256=08iUcYud3aEHuQcUsem9bWNxdXKgaxFbMy9yvtr-DZQ,6995
7
7
  pytbox/pyjira.py,sha256=TMy34Rtu7OXRA8wpUuLsFeyIQfRNUn2ed2no00L8YSE,22470
8
8
  pytbox/vmware.py,sha256=WiH67_3-VCBjXJuh3UueOc31BdZDItiZhkeuPzoRhw4,3975
9
9
  pytbox/alert/alert_handler.py,sha256=FePPQS4LyGphSJ0QMv0_pLWaXxEqsRlcTKMfUjtsNfk,5048
10
- pytbox/alert/ping.py,sha256=g36X0U3U8ndZqfpVIcuoxJJ0X5gST3I_IwjTQC1roHA,779
11
- pytbox/alicloud/sls.py,sha256=UR4GdI86dCKAFI2xt_1DELu7q743dpd3xrYtuNpfC5A,4065
10
+ pytbox/alert/ping.py,sha256=KEnnXdIRJHvR_rEHPWLBt0wz4cGwmA29Lenlak3Z_1Y,778
11
+ pytbox/alicloud/sls.py,sha256=-r6rbCwDUQ4jwAgSVSNu7B2h1MNg20CrRIKnlXVeY9w,4159
12
12
  pytbox/categraf/build_config.py,sha256=9G85rLqkz3lchpH7ef0LbvckYHl0nRA6mHVLeUfs9Mw,6308
13
13
  pytbox/categraf/instances.toml,sha256=jcJyEaqhohUcECczWArxUK4t0-rdk4vmrX21kxZlSLA,1254
14
14
  pytbox/categraf/jinja2/__init__.py,sha256=Epm01j8Oujeg4Sk5GgHMvgKIZ6h3BTx-MGmuMgIjUMo,150
@@ -43,28 +43,28 @@ pytbox/cli/formatters/__init__.py,sha256=4o85w4j-A-O1oBLvuE9q8AFiJ2C9rvB3MIKsy5V
43
43
  pytbox/cli/formatters/output.py,sha256=h5WhZlQk1rjmxEj88Jy5ODLcv6L5zfGUhks_3AWIkKU,5455
44
44
  pytbox/common/__init__.py,sha256=3JWfgCQZKZuSH5NCE7OCzKwq82pkyop9l7sH5YSNyfU,122
45
45
  pytbox/database/mongo.py,sha256=CSpHC7iR-M0BaVxXz5j6iXjMKPgXJX_G7MrjCj5Gm8Q,3478
46
- pytbox/database/victoriametrics.py,sha256=wTTsCOMpUpia8Bhp3clpFrUo3ow0T822MnZMxJnXRVM,5392
46
+ pytbox/database/victoriametrics.py,sha256=3lLbcqDADojkFH52OcJaz2ApxWnAD_pnqkMQR8fditI,11295
47
47
  pytbox/feishu/client.py,sha256=kwGLseGT_iQUFmSqpuS2_77WmxtHstD64nXvktuQ3B4,5865
48
48
  pytbox/feishu/endpoints.py,sha256=z3nPOZPC2JGDJlO7SusWBpRA33hZZ4Z-GBhI6F8L_u4,40240
49
49
  pytbox/feishu/errors.py,sha256=79qFAHZw7jDj3gnWAjI1-W4tB0q1_aSfdjee4xzXeuI,1179
50
50
  pytbox/feishu/helpers.py,sha256=jhSkHiUw4822QBXx2Jw8AksogZdakZ-3QqvC3lB3qEI,201
51
51
  pytbox/feishu/typing.py,sha256=3hWkJgOi-v2bt9viMxkyvNHsPgrbAa0aZOxsZYg2vdM,122
52
- pytbox/log/logger.py,sha256=7ZisXRxLb_MVbIqlYHWoTbj1EA0Z4G5SZvITlt1IKW8,7416
52
+ pytbox/log/logger.py,sha256=tfqRc7VcDyI_U-NiiK4euFe8O2ro9yeXVohPmzAC_hY,8867
53
53
  pytbox/log/victorialog.py,sha256=gffEiq38adv9sC5oZeMcyKghd3SGfRuqtZOFuqHQF6E,4139
54
54
  pytbox/mail/alimail.py,sha256=njKA3PUbIaiKFaxKvUObmklmEEHg2YA-O5rpgsgT5_w,5147
55
55
  pytbox/mail/client.py,sha256=6HeKpChHGjTCYGBgQcfAhWlU_wh9wtO-bjP6TU38pGM,6120
56
56
  pytbox/mail/mail_detail.py,sha256=6u8DK-7WzYPSuX6TdicSCh2Os_9Ou6Rn9xc6WRvv85M,699
57
57
  pytbox/network/meraki.py,sha256=054E3C5KzAuXs9aPalvdAOUo6Hc5aOKZSWUaVbPquy4,6112
58
+ pytbox/utils/cronjob.py,sha256=b17CY1fmaFTdQojicXAXHliov_JZdmT7cZhtO4v5sCo,3080
58
59
  pytbox/utils/env.py,sha256=gD2-NyL3K3Vg1B1eGeD1hRtlSHPGgF8Oi9mchuQL6_o,646
59
60
  pytbox/utils/load_config.py,sha256=R4pGerBinbewsym41hQ8Z-I5I7gepuEKODjIrli4C08,5043
60
61
  pytbox/utils/load_vm_devfile.py,sha256=GVbB-FvGb0l586SDaraz__ZaXyDWd1WxcXVw5xGfXWw,1328
61
- pytbox/utils/ping_checker.py,sha256=Nqnn8clbgv-5l0PgxcTOldg8mkMKrFn4TvPL-rYUUGg,1
62
62
  pytbox/utils/response.py,sha256=kXjlwt0WVmLRam2eu1shzX2cQ7ux4cCQryaPGYwle5g,1247
63
63
  pytbox/utils/richutils.py,sha256=OT9_q2Q1bthzB0g1GlhZVvM4ZAepJRKL6a_Vsr6vEqo,487
64
64
  pytbox/utils/timeutils.py,sha256=uSKgwt20mVcgIGKLsH2tNum8v3rcpzgmBibPvyPQFgM,20433
65
65
  pytbox/win/ad.py,sha256=-3pWfL3dElz-XoO4j4M9lrgu3KJtlhrS9gCWJBpafAU,1147
66
- pytbox-0.1.5.dist-info/METADATA,sha256=hIq6VA2Lt7Y0T3nZgFuP1K_ug-pcckGJ3olhE4cc4Bg,6319
67
- pytbox-0.1.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
68
- pytbox-0.1.5.dist-info/entry_points.txt,sha256=YaTOJ2oPjOiv2SZwY0UC-UA9QS2phRH1oMvxGnxO0Js,43
69
- pytbox-0.1.5.dist-info/top_level.txt,sha256=YADgWue-Oe128ptN3J2hS3GB0Ncc5uZaSUM3e1rwswE,7
70
- pytbox-0.1.5.dist-info/RECORD,,
66
+ pytbox-0.1.7.dist-info/METADATA,sha256=F1iAjEaYwI8n3pUxQn22V4Zcavu_W0Toz4scTHxwg0c,6319
67
+ pytbox-0.1.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
68
+ pytbox-0.1.7.dist-info/entry_points.txt,sha256=YaTOJ2oPjOiv2SZwY0UC-UA9QS2phRH1oMvxGnxO0Js,43
69
+ pytbox-0.1.7.dist-info/top_level.txt,sha256=YADgWue-Oe128ptN3J2hS3GB0Ncc5uZaSUM3e1rwswE,7
70
+ pytbox-0.1.7.dist-info/RECORD,,
@@ -1 +0,0 @@
1
-
File without changes