skywalking本身的报警功能,用起来视乎不是特别好用,目前想实现对skywalking的trace中的错误接口进行过滤并报警通知管理员和开发。所以自己就用python对skywalking做了二次数据清洗实现。项目方在了自己了github(https://github.com/shygit-dev/skywalking-cli-python)上了,有兴趣的同学可以做二次改造,共同学习。下面简单列出了代码内容:

sw-trace.py

#!/usr/bin/env python
# _*_ coding: utf-8 _*_
# Tile:
# Author:shy
import requests
import time
import smtplib
from email.mime.text import MIMEText
import re

def interface_content_filter(trace_id):
'''
对详细日志内容(业务逻辑报错)进行过滤
:param trace_id:
:return: 【1|0】
'''
url = "http://172.16.53.232:50001/query"
params = {
"trace_id": trace_id
}
detail_trace_id_log = requests.request(method="GET",url=url,params=params)
detail_trace_id_log = detail_trace_id_log.text
print(detail_trace_id_log)
print(type(detail_trace_id_log))
with open("blackname_keyword_list","r",encoding="utf-8") as f:
for line in f:
print(line)
result = re.search(line.strip(),detail_trace_id_log)
print(result)
if result != None:
print("哥们匹配到日志黑名单关键字了:%s" % line)
return 0
print("提示:%s不在关键字黑名单中" % trace_id)
return 1

def interface_filter(endpointName):
"""
设置接口黑名单
:param endpointName:
:return: 【1|0】
"""
endpointName = re.sub("\(|\)",".",endpointName)
with open("blackname_list","r",encoding="utf-8") as f:
bn_list = f.read()
match_result = re.search(endpointName.strip(),bn_list)
if match_result == None:
print("提示:接口不存在黑名单中")
return 1
print("提示:接口在黑名单中")
return 0

def trace_erro_interface(start_time,end_time,sw_url,per_page_size,trace_detail_addr):
"""
skywalking trace功能对错误接口进行过滤,默认最大一次获取2000条数据,每分钟执行一次
:param start_time:
:param end_time:
:return:
"""
url = sw_url
data = {
"query": "query queryTraces($condition: TraceQueryCondition) {\n data: queryBasicTraces(condition: $condition) {\n traces {\n key: segmentId\n endpointNames\n duration\n start\n isError\n traceIds\n }\n total\n }}",
"variables": {
"condition": {
"queryDuration": {
"start": start_time, #"2021-12-07 1734"
"end": end_time,
"step": "MINUTE"
},
"traceState": "ERROR",
"paging": {
"pageNum": 1,
"pageSize": per_page_size,
"needTotal": "true"
},
"queryOrder": "BY_START_TIME"
# "traceId": "b669d0069be84fce82261901de412e7c.430.16388637511348105"
}
}
}

result = requests.request(method="post",url=url,json=data)
i = 0
# print(result.content)
# print(time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(float("%s.%s" % (trace["start"][0:10],trace["start"][10:])))))
with open("mail.html","w",encoding="utf-8") as f:
f.write('<head><meta charset="UTF-8"><title>Title</title><style>.t {border-right: 2px solid black;border-bottom: 2px solid black;}.t th,td {border-top: 2px solid black;border-left: 2px solid black;font-size: 10px;}</style></head><body><div style="color:red;font-size=15px;">最近15分钟统计:</div><table class="t" border="0" cellspacing="0" cellpadding="10px"><thead><tr style="<th style="width: 100px;">时间</th><th>持续时长</th><th>接口名称</th><th>追踪ID</th></tr></thead><tbody>')
for trace in result.json()["data"]["data"]["traces"]:
# print(trace["endpointNames"])
print("时间:%s\n" % time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(float("%s.%s" % (trace["start"][0:10],trace["start"][10:])))),
"持续时长:%s\n" % trace["duration"],
"接口名称:%s\n" % trace["endpointNames"][0],
"跟踪ID:%s" % trace["traceIds"][0])
# print(time.localtime(1638869640.194))
i+=1
print(i)
s_time = time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(float("%s.%s" % (trace["start"][0:10],trace["start"][10:]))))
dur_time = trace["duration"]
endpointName = trace["endpointNames"][0]
trace_id = trace["traceIds"][0]

# 调用接口黑名单过滤功能
result = interface_filter(endpointName)
if result == 0:
print("哥们进入黑名单了!",endpointName)
continue
# 调用关键字黑名单过滤功能
keyword_result = interface_content_filter(trace_id)
if keyword_result == 0:
print("哥们进入关键字黑名单了!", trace_id)
continue

with open("mail.html","a",encoding="utf-8") as f:
f.write('<tr><td>%s</td><td>%s</td><td>%s</td><td><a href="http://%s/query?trace_id=%s">%s</a></td></tr>' %(s_time,dur_time,endpointName,trace_detail_addr,trace_id,trace_id))
with open("mail.html","a",encoding="utf-8") as f:
f.write('</tbody></table></body>')

def send_mail(receiver):
"""
发送报错接口邮件
:return:
"""
server = "mail.test.com"
sender = "sa@test.com"
sender_pwd = "1qaz@WSX"
send_addr = "sa@test.com"

receiver = receiver
with open("mail.html","r",encoding="utf-8") as f:
content = f.read()
if re.search("<td>",content) == None:
print("无报错接口!",content)
return 0
print("邮件前",content)
msg_mail = MIMEText(content,"html","utf-8")
msg_mail["Subject"] = "Skywalking报错接口统计"
msg_mail["From"] = sender
msg_mail["To"] = receiver

server_obj = smtplib.SMTP_SSL(server)
server_obj.connect(server,465)
server_obj.login(sender,sender_pwd)
server_obj.sendmail(send_addr,receiver,msg_mail.as_string())

if __name__ == "__main__":
# 设定查询时间间隔,默认900s(15min)
end_time = time.time()
start_time = end_time - 900
start_time=time.strftime("%Y-%m-%d %H%M",time.localtime(start_time))
end_time = time.strftime("%Y-%m-%d %H%M", time.localtime(end_time))
print(start_time)
print(end_time)
sw_url = "http://172.16.53.232:9412/graphql" # skywalking的前端服务的地址和端口
per_page_size = 5000 #指定一次获取endpoint接口的数目
trace_detail_addr = "127.0.0.1:5000" #指定查询指定trace_id详细日志

receiver = "shy@test.com" #报警邮件接收人地址

trace_erro_interface(start_time,end_time,sw_url,per_page_size,trace_detail_addr)
send_mail(receiver)
# interface_filter()
# interface_content_filter("3c4212dd2dd548d394ba312c4619405d.104.16390380592724487")

sw-trace-id.py

#!/usr/bin/env python
# _*_ coding: utf-8 _*_
# Tile:
# Author:shy
import requests
import time
from flask import Flask,request
app = Flask(__name__)

@app.route("/query",methods=["get"])
def trace_id_query():
"""
查询指定trace_id详细日志信息
:return: f.read()
"""
trace_id = request.args.get("trace_id")
url="http://172.16.53.232:9412/graphql"
# url="http://skywalking.roulw.com/graphql"
data = {
"query": "query queryTrace($traceId: ID!) {\n trace: queryTrace(traceId: $traceId) {\n spans {\n traceId\n segmentId\n spanId\n parentSpanId\n refs {\n traceId\n parentSegmentId\n parentSpanId\n type\n }\n serviceCode\n serviceInstanceName\n startTime\n endTime\n endpointName\n type\n peer\n component\n isError\n layer\n tags {\n key\n value\n }\n logs {\n time\n data {\n key\n value\n }\n }\n }\n }\n }",
"variables": {
"traceId": trace_id
}
}

result = requests.request(method="post",url=url,json=data)
with open("detail_log", "w", encoding="utf-8") as f:
f.write("<div style='color: red;font-size: 30px;'>生产Skywalking报错接口跟踪日志日志:<br /></div>")
for trace_id in result.json()["data"]["trace"]["spans"]:

if trace_id["isError"]:
# print(trace_id)
print("服务名称:%s\n" % trace_id["serviceCode"],
"开始时间:%s\n" % trace_id["startTime"],
"接口名称:%s\n" % trace_id["endpointName"],
"peer名称:%s\n" % trace_id["peer"],
"tags名称:%s\n" % trace_id["tags"],
"详细日志:%s" % trace_id["logs"])
content = "服务名称:%s<br />开始时间:%s<br />接口名称:%s<br />peer名称:%s<br />tags名称:%s" % (trace_id["serviceCode"],trace_id["startTime"],trace_id["endpointName"],trace_id["peer"],trace_id["tags"])
with open("detail_log","a",encoding="utf-8") as f:
f.write(content)
f.write("<br />********详细日志**********<br />")
for logs in trace_id["logs"]:
for log in logs["data"]:
if log["key"] == "message":
print(log["value"])
with open("detail_log","a",encoding="utf-8") as f:
f.write(log["value"])
# return log["value"]
elif log["key"] == "stack":
print(log["value"])
with open("detail_log","a",encoding="utf-8") as f:
f.write(log["value"])
with open("detail_log", "a", encoding="utf-8") as f:
f.write("<div style='color: red;font-size: 20px;'><br />========下一个接口信息=========<br /></div>")
with open("detail_log","r",encoding="utf-8") as f:
return f.read()

if __name__ == "__main__":
# trace_id = "14447ae7199c40a2b9862411daba180b.2142.16388920322367785"
# trace_id_query(trace_id)
app.run()

python实现skywalking的trace模块过滤和报警的更多相关文章

  1. Python开发之日志记录模块:logging

    1 引言 最近在开发一个应用软件,为方便调试和后期维护,在代码中添加了日志,用的是Python内置的logging模块,看了许多博主的博文,颇有所得.不得不说,有许多博主大牛总结得确实很好.似乎我再写 ...

  2. python之旅:常用模块

    一.time与datetime模块 在Python中,通常有这几种方式来表示时间 时间戳(timestamp):通常来说,时间戳表示的是从1970年1月1号00:00:00开始按照秒计算的偏移量.我们 ...

  3. python基础学习十 logging模块详细使用【转载】

    很多程序都有记录日志的需求,并且日志中包含的信息既有正常的程序访问日志,还可能有错误.警告等信息输出,python的logging模块提供了标准的日志接口,你可以通过它存储各种格式的日志,主要用于输出 ...

  4. python基础(10)--模块

    模块(module) 模块,用一坨代码实现了某个功能的代码集合 类似于函数式编程和面向过程编程,函数式编程则完成一个功能,其他代码用来调用即可,提供了代码的重用性和代码间的耦合.而对于一个复杂的功能来 ...

  5. Python之日志处理 logging模块

    Python之日志处理(logging模块)   本节内容 日志相关概念 logging模块简介 使用logging提供的模块级别的函数记录日志 logging模块日志流处理流程 使用logging四 ...

  6. python中常⽤的excel模块库

    python中常用的excel模块库&安装方法 openpyxl openpyxl是⼀个Python库,用于读取/写⼊Excel 2010 xlsx / xlsm / xltx / xltm⽂ ...

  7. Python全栈开发【模块】

    Python全栈开发[模块] 本节内容: 模块介绍 time random os sys json & picle shelve XML hashlib ConfigParser loggin ...

  8. Python 学习笔记(6)--常用模块(2)

    一.下载安装 下载安装有两种方式: yum\pip\apt-get 或者源码 下载源码 解压源码 进入目录 编译源码 python setup.py build 安装源码 python setup.p ...

  9. python学习笔记之常用模块(第五天)

    参考老师的博客: 金角:http://www.cnblogs.com/alex3714/articles/5161349.html 银角:http://www.cnblogs.com/wupeiqi/ ...

随机推荐

  1. 大一C语言学习笔记(11)---编程篇--写一个程序,可以获取从键盘上输入的的三个数,并能够判断是否可以以这三个数字作为边长来构成一个三角形,如果可以的话,输出此三角形的周长及面积,要求 0 bug;

    考核内容: 写一个程序,可以获取从键盘上输入的的三个数,并能够判断是否可以以这三个数字作为边长来构成一个三角形,如果可以的话,输出此三角形的周长及面积: 答案: #include<stdio.h ...

  2. 「期末」一文带你系统回顾C 语言

    超详细 c 语言回顾 前言 c 语言是一种底层语言,是一种系统底层级的语言,例如Windows.Linux.Unix等操作系统就是使用c语言编写的.所以由此看来,不论是火爆了25年的Java,还是近年 ...

  3. 使用.NET5、Blazor和Electron.NET构建跨平台桌面应用

    Electron.NET是一个嵌入了ASP.NET Core的Electron的封装,通过Electron.NET可以构建基于.NET5的跨平台的桌面应用,使得开发人员只需要使用ASP.NET Cor ...

  4. [hdu7062]A Simple Problem

    称序列$\{a_{1},a_{2},...,a_{n}\}$​的答案为$\min_{0\le i\le n-k}(\max_{i<j\le i+k}a_{j})$​​(特别的,若$n<k$ ...

  5. [spojSUBST1]New Distinct Substrings

    求出后缀数组和height数组,然后因为子串即后缀的前缀,考虑不断新增后缀然后计算贡献,如果以sa的顺序新增那么第i个就会产生n-sa[k]+1-h[k](n-sa[k]+1为总方案,h为不合法的方案 ...

  6. [noi1760]SAM

    建立SAM,求出每一个节点最左边的出现位置(即right集合中的最小元素,在树上dfs即可) 枚举左端点i和右端点j(保证j是最小的满足$s[i,j)$不是$s[0,i)$的子串),维护k表示$s[i ...

  7. 「后端小伙伴来学前端了」Vuex进阶操作,让你的代码更加高效(简称如何学会偷懒 【手动狗头】)

    学妹手机里的美照 前言 前一篇写了Vuex基本使用,用起来还稍稍有些繁琐,代码有很多 冗余的地方,这篇就带着大家用更简单的方式来使用Vuex(其实就是怎么更好的偷懒,用更少的代码来完之前的事情) 进入 ...

  8. 关于前端项目cookie的获取

    最近项目在做切换,2.0要升级到3.0,遇到跨域问题,使用的是nginx 进行对端口拦截请求其他地址,另外有的服务还要登录权限,之前没看到有这个,后来加上获取cookie的请求 var v3_toke ...

  9. vue create is a Vue CLI 3 only command and you are using Vue CLI 2.9.6. You

    这是因为你安装的是2.9的版本用了3.0的命令 解决方法:1.用2.9的命令初始化项目 vue init webpack my-project 2.卸载2.9升级到3.0

  10. 主动扫描之Nmap

    主动扫描之Nmap 本文参考于李华峰等人的图书<Kali Linux2 网络渗透测试实践指南>2018年第1版 目录 主动扫描之Nmap 基本用法 主机发现 端口发现 扫描目标操作系统 扫 ...