pytbox 0.1.6__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 +0 -1
- pytbox/base.py +6 -1
- pytbox/database/victoriametrics.py +103 -7
- pytbox/utils/cronjob.py +79 -0
- {pytbox-0.1.6.dist-info → pytbox-0.1.7.dist-info}/METADATA +1 -1
- {pytbox-0.1.6.dist-info → pytbox-0.1.7.dist-info}/RECORD +9 -9
- pytbox/utils/ping_checker.py +0 -1
- {pytbox-0.1.6.dist-info → pytbox-0.1.7.dist-info}/WHEEL +0 -0
- {pytbox-0.1.6.dist-info → pytbox-0.1.7.dist-info}/entry_points.txt +0 -0
- {pytbox-0.1.6.dist-info → pytbox-0.1.7.dist-info}/top_level.txt +0 -0
pytbox/alert/ping.py
CHANGED
pytbox/base.py
CHANGED
|
@@ -16,6 +16,7 @@ from pytbox.pyjira import PyJira
|
|
|
16
16
|
from pytbox.mail.client import MailClient
|
|
17
17
|
from pytbox.mail.alimail import AliMail
|
|
18
18
|
from pytbox.alicloud.sls import AliCloudSls
|
|
19
|
+
from pytbox.utils.cronjob import cronjob_counter
|
|
19
20
|
|
|
20
21
|
|
|
21
22
|
config = load_config_by_file(path='/workspaces/pytbox/tests/alert/config_dev.toml', oc_vault_id=os.environ.get('oc_vault_id'))
|
|
@@ -107,4 +108,8 @@ sls = AliCloudSls(
|
|
|
107
108
|
access_key_secret=config['alicloud']['account1']['access_key_secret'],
|
|
108
109
|
project=config['alicloud']['account1']['project'],
|
|
109
110
|
logstore=config['alicloud']['account1']['logstore']
|
|
110
|
-
)
|
|
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,7 +18,44 @@ 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
|
+
"""插入指标数据。
|
|
26
|
+
|
|
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
|
+
}
|
|
20
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
|
+
|
|
21
59
|
def query(self, query: str=None, output_format: Literal['json']=None) -> ReturnResponse:
|
|
22
60
|
'''
|
|
23
61
|
查询指标数据
|
|
@@ -208,9 +246,67 @@ class VictoriaMetrics:
|
|
|
208
246
|
'''
|
|
209
247
|
q = f"""avg_over_time(snmp_interface_ifOperStatus{{sysName="{sysname}", ifName="{if_name}"}}[{last_minute}m])"""
|
|
210
248
|
r = self.query(query=q)
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
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)
|
|
214
256
|
else:
|
|
215
|
-
|
|
216
|
-
|
|
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/utils/cronjob.py
ADDED
|
@@ -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,4 +1,4 @@
|
|
|
1
|
-
pytbox/base.py,sha256=
|
|
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,7 +7,7 @@ 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=
|
|
10
|
+
pytbox/alert/ping.py,sha256=KEnnXdIRJHvR_rEHPWLBt0wz4cGwmA29Lenlak3Z_1Y,778
|
|
11
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
|
|
@@ -43,7 +43,7 @@ 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=
|
|
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
|
|
@@ -55,16 +55,16 @@ 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.
|
|
67
|
-
pytbox-0.1.
|
|
68
|
-
pytbox-0.1.
|
|
69
|
-
pytbox-0.1.
|
|
70
|
-
pytbox-0.1.
|
|
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,,
|
pytbox/utils/ping_checker.py
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
|
|
File without changes
|
|
File without changes
|
|
File without changes
|