master
luziqi 2 years ago
parent 8a1f6f2daa
commit cb1b950c1f

@ -12,13 +12,15 @@ import (
const API_tbapi = "http://qa.flatincbr.work:5354"
const BugCategory_Anomaly = "monkey异常"
const BugCategory_Anomaly_adr = "monkey异常-安卓端"
const BugCategory_Anomaly_ios = "monkey异常-iOS端"
type BugInfo struct {
ProjectName string `json:"project_name"` // tb项目名称
Category string `json:"category"` // 提单配置中的缺陷类型
Title string `json:"title"` // tb缺陷的标题
Content string `json:"content"` // tb缺陷的备注
Pf string `json:"pf"` // 所属平台除了adr/ios其它不处理
Platform string `json:"platform"` // 所属平台除了adr/ios其它不处理
}
func NewBug(project_name string) BugInfo {
@ -47,7 +49,7 @@ func (b *BugInfo) SetContent(content string) *BugInfo {
// 设置所属平台adr/ios
func (b *BugInfo) SetPlatform(pf string) *BugInfo {
b.Pf = pf
b.Platform = pf
return b
}

@ -27,6 +27,11 @@ func PushDingTalk() {
// push.SendActionCardMessage()
}
func PushLog(title, str string) {
cli := dingtalk.InitDingTalkWithSecret(Bot_Test_Token, Bot_Test_Secret)
cli.SendMarkDownMessage(title, str)
}
func PushCorntaskLog(str string) {
cli := dingtalk.InitDingTalkWithSecret(Bot_Test_Token, Bot_Test_Secret)
cli.SendMarkDownMessage("定时任务", str)

@ -47,14 +47,22 @@ func CheckMonkeyTasks() {
if strings.Contains(task.Product, "-") {
product_name = strings.Split(task.Product, "-")[0]
}
var d models.Device
db.Table("device").Model(models.Device{}).Where("project = ? AND product_name = ? AND platform = ? AND status = ?", task.Project, product_name, task.Platform, "online").First(&d)
// 获取product.id
var _p models.QaProduct
db_oms.Table(_p.TableName()).Model(models.QaProduct{}).Where("label = ?", product_name).Last(&_p)
if _p.ID < 1 {
fmt.Println("找不到产品,", product_name)
// 找不到对应的产品
continue
}
var d models.DeviceV2
db_oms.Table("qa_devices").Model(models.DeviceV2{}).Where("product_id = ? AND platform = ? AND status = ? AND is_enabled = 1", _p.ID, task.Platform, "online").First(&d)
if d.ID < 1 {
// 没有空闲设备
continue
}
// 占用设备
db.Table("device").Model(models.Device{}).Where("udid = ?", d.Udid).Update("status", "busy")
db_oms.Table("qa_devices").Model(models.DeviceV2{}).Where("udid = ?", d.Udid).Update("status", "busy")
go monkey.RunAndroidMonkeyCmd(task, d.Udid)
db.Table(task.TableName()).Model(models.MonkeyTask{}).Where("id = ?", task.Id).Update("start_time", time.Now().Unix())
common.PushCorntaskLog("执行Monkey任务" + task.Project + "-" + d.Udid)
@ -109,6 +117,8 @@ func CheckMonkeyTasks() {
list[i].Status = "FINISH"
db.Table(v.TableName()).Model(models.MonkeyTask{}).Where("id = ?", v.Id).Update("status", list[i].Status)
db.Table(v.TableName()).Model(models.MonkeyTask{}).Where("id = ?", v.Id).Update("end_time", time.Now().Unix())
// 释放设备
db_oms.Table("qa_devices").Model(models.DeviceV2{}).Where("udid = ?", v.Devices).Update("status", "online")
common.PushCorntaskLog("[autogo] 任务标记为FINISH, 但容器未退出, task_id=" + cast.ToString(v.Id))
}

@ -1353,6 +1353,48 @@ const docTemplate = `{
}
}
},
"/api/tool/v1/bigdata/query": {
"get": {
"description": "通过指定一些参数查询打点数据",
"consumes": [
"application/x-www-form-urlencoded"
],
"tags": [
"工具相关 /api/tool/v1/"
],
"summary": "埋点查询",
"parameters": [
{
"type": "string",
"description": "产品key",
"name": "project_key",
"in": "query",
"required": true
},
{
"type": "string",
"description": "过滤关键字可以是action也可以是打点内容模糊匹配,多个用逗号分隔",
"name": "keyword",
"in": "query",
"required": true
},
{
"type": "integer",
"description": "请求数量默认为10",
"name": "count",
"in": "query"
}
],
"responses": {
"200": {
"description": "返回打点信息",
"schema": {
"$ref": "#/definitions/models.Response"
}
}
}
}
},
"/api/tool/v1/voice/list": {
"get": {
"description": "根据表单id获取声音评测内容返回分组和分组文件信息",

@ -1341,6 +1341,48 @@
}
}
},
"/api/tool/v1/bigdata/query": {
"get": {
"description": "通过指定一些参数查询打点数据",
"consumes": [
"application/x-www-form-urlencoded"
],
"tags": [
"工具相关 /api/tool/v1/"
],
"summary": "埋点查询",
"parameters": [
{
"type": "string",
"description": "产品key",
"name": "project_key",
"in": "query",
"required": true
},
{
"type": "string",
"description": "过滤关键字可以是action也可以是打点内容模糊匹配,多个用逗号分隔",
"name": "keyword",
"in": "query",
"required": true
},
{
"type": "integer",
"description": "请求数量默认为10",
"name": "count",
"in": "query"
}
],
"responses": {
"200": {
"description": "返回打点信息",
"schema": {
"$ref": "#/definitions/models.Response"
}
}
}
}
},
"/api/tool/v1/voice/list": {
"get": {
"description": "根据表单id获取声音评测内容返回分组和分组文件信息",

@ -929,6 +929,34 @@ paths:
summary: 更新Bugly凭据
tags:
- 设置相关 /api/setting/v2/
/api/tool/v1/bigdata/query:
get:
consumes:
- application/x-www-form-urlencoded
description: 通过指定一些参数查询打点数据
parameters:
- description: 产品key
in: query
name: project_key
required: true
type: string
- description: 过滤关键字可以是action也可以是打点内容模糊匹配,多个用逗号分隔
in: query
name: keyword
required: true
type: string
- description: 请求数量默认为10
in: query
name: count
type: integer
responses:
"200":
description: 返回打点信息
schema:
$ref: '#/definitions/models.Response'
summary: 埋点查询
tags:
- 工具相关 /api/tool/v1/
/api/tool/v1/voice/list:
get:
consumes:

@ -126,6 +126,12 @@ func createTbBug(ano models.MonkeyAnomaly) {
}
defer dbsql.Close(db)
// 先查询当前monkey任务已有的异常
var list []models.MonkeyAnomaly
db.Table(ano.TableName()).Model(models.MonkeyAnomaly{}).Where("task_id = ?", ano.TaskId).Find(&list)
// 标记当前异常是否已上报过
is_exist := false
var task models.MonkeyTask
db.Model(models.MonkeyTask{}).Where("id = ?", ano.TaskId).Last(&task)
if task.Id < 1 {
@ -152,7 +158,7 @@ func createTbBug(ano models.MonkeyAnomaly) {
content += "> " + vv + "\n"
switch bug_type {
case "EXCEPTION":
// 取第一行和第三行内容拼接
// 取第一行(异常发生未知)和第三行(异常类型)内容拼接
if i == 0 && ii == 0 {
_strs := strings.Split(vv, "): ")
if len(_strs) > 1 {
@ -162,6 +168,13 @@ func createTbBug(ano models.MonkeyAnomaly) {
_strs := strings.Split(vv, "): ")
if len(_strs) > 1 {
title += _strs[1]
// 比较历史异常中是否已经出现
for _, v := range list {
if strings.Contains(v.AnomalyInfos, _strs[1]) {
// 相似,不上报了,但还是会存库里
is_exist = true
}
}
}
}
default:
@ -178,12 +191,24 @@ func createTbBug(ano models.MonkeyAnomaly) {
content += "> " + "(...更多请查看Monkey报告)" + "\n"
content += "\n"
// 如果已标记当前异常已经上报过,则跳过提单逻辑
if is_exist {
// 这里可以再额外处理
common.PushLog("Monkey", "相似异常已存在不再提单task_id="+cast.ToString(ano.TaskId)+"\n"+title)
return
}
// 初始化提单bug对象
bug := common.NewBug(task.Project) // task.Project
bug.SetTitle(title).
SetPlatform(task.Platform).
SetContent(content).
SetCategory(common.BugCategory_Anomaly)
SetContent(content)
if task.Platform == "adr" {
bug.SetCategory(common.BugCategory_Anomaly_adr)
} else {
bug.SetCategory(common.BugCategory_Anomaly_ios)
}
id, err := bug.Create()
if err != nil {

@ -57,6 +57,13 @@ func GetDevicesByTaskId(c *gin.Context) {
return
}
defer dbsql.Close(db)
db_oms, err := dbsql.GetConn(dbsql.DSN_qaoms())
if err != nil {
rsp.Error(err.Error())
c.JSON(http.StatusOK, rsp)
return
}
defer dbsql.Close(db_oms)
var task models.MonkeyTask
db.Model(models.MonkeyTask{}).Where("id = ?", task_id).Last(&task)
@ -67,19 +74,19 @@ func GetDevicesByTaskId(c *gin.Context) {
return
}
var devices []models.Device
var devices []models.DeviceV2
if strings.Contains(task.Devices, ",") {
list := strings.Split(task.Devices, ",")
for _, v := range list {
var d models.Device
db.Model(models.Device{}).Where("udid = ?", v).Last(&d)
var d models.DeviceV2
db_oms.Model(models.DeviceV2{}).Where("udid = ?", v).Last(&d)
if d.ID > 0 {
devices = append(devices, d)
}
}
} else {
var d models.Device
db.Model(models.Device{}).Where("udid = ?", task.Devices).Last(&d)
var d models.DeviceV2
db_oms.Model(models.DeviceV2{}).Where("udid = ?", task.Devices).Last(&d)
if d.ID > 0 {
devices = append(devices, d)
}

@ -0,0 +1,166 @@
package qatool
import (
"autogo/controllers"
"crypto/md5"
"encoding/hex"
"fmt"
"net/http"
"sort"
"strings"
"time"
"github.com/gin-gonic/gin"
"github.com/imroc/req/v3"
"github.com/spf13/cast"
)
type BigData struct {
Keyword string `json:"keyword"`
Action string `json:"action"`
Did string `json:"did"`
PkgName string `json:"pkg_name"`
RawData string `json:"raw_data"`
SLogTime string `json:"slogtime"`
LogTime int64 `json:"logtime"`
MD5 string `json:"md5"`
}
// 实现 sort.Interface 接口的 Len、Less 和 Swap 方法
type BigDataList []BigData
func (a BigDataList) Len() int { return len(a) }
func (a BigDataList) Less(i, j int) bool { return a[i].LogTime < a[j].LogTime }
func (a BigDataList) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
// @Tags 工具相关 /api/tool/v1/
// @Summary 埋点查询
// @Description 通过指定一些参数查询打点数据
// @accept x-www-form-urlencoded
// @Param project_key query string true "产品key"
// @Param action query string false "过滤action事件"
// @Param keyword query string false "过滤关键字可以是action也可以是打点内容模糊匹配,多个用逗号分隔"
// @Param count query int false "请求数量默认为10"
// @Param did query string false "可选-did过滤"
// @Param pkg query string false "可选-包名过滤"
// @Success 200 {object} models.Response "返回打点信息"
// @Router /api/tool/v1/bigdata/query [get]
func GetProjectBigData(c *gin.Context) {
rsp := controllers.NewResponse()
var actions []string
// 访问日志路径需要的产品参数
project_key := c.Query("project_key")
if project_key == "" {
c.JSON(http.StatusOK, rsp.Error("project_key needed"))
return
}
// filter-传入did以过滤
did := c.DefaultQuery("did", "")
// 获取事件名称
action := c.Query("action")
if action == "" {
c.JSON(http.StatusOK, rsp.Error("action or keyword needed"))
return
}
if strings.Contains(action, ",") {
actions = strings.Split(action, ",")
} else {
actions = append(actions, action)
}
count := cast.ToInt(c.DefaultQuery("count", "10"))
pkg_name := c.Query("pkg")
// 开始获取数据处理...
var list []BigData
for _, v := range actions {
_list := GetBigData(project_key, did, "action="+v, count)
for _, vv := range _list {
var bd BigData
bd.Keyword = v
bd.RawData = vv
for _, vvv := range strings.Split(vv, "`") {
if strings.Split(vvv, "=")[0] == "action" {
bd.Action = strings.Split(vvv, "=")[1]
}
if strings.Split(vvv, "=")[0] == "did" {
bd.Did = strings.Split(vvv, "=")[1]
}
if strings.Split(vvv, "=")[0] == "pkg" {
bd.PkgName = strings.Split(vvv, "=")[1]
}
if strings.Split(vvv, "=")[0] == "logtime" {
bd.LogTime = cast.ToInt64(strings.Split(vvv, "=")[1])
}
if strings.Split(vvv, "=")[0] == "slogtime" {
bd.SLogTime = strings.Split(vvv, "=")[1]
}
}
md5Hash := md5.Sum([]byte(vv))
bd.MD5 = hex.EncodeToString(md5Hash[:])
// 为空 或者 包名与数据匹配
if pkg_name == "" || pkg_name == bd.PkgName {
list = append(list, bd)
}
}
}
// 遍历获取到的数据,初步解析
// 使用 sort.Sort 函数进行排序
sort.Sort(BigDataList(list))
rsp.Success()
rsp.Data = list
c.JSON(http.StatusOK, rsp)
}
func GetBigData(project_key, did, kw string, count int) []string {
var strs []string
m := make(map[string]string)
m["filepath"] = "apps/odps_app_log/action_log/app_" + project_key + "_action_" + getTodayStr() + ".log"
m["filter"] = did // "ad82204d-b395-4000-9a6c-c693bb859dec"
m["keywords"] = kw //"on_time"
m["count"] = cast.ToString(count)
resp, err := req.
SetQueryParams(m).
Get("http://47.74.249.92:7912/log/grep")
if err != nil {
fmt.Println(err)
return strs
}
if resp.IsErrorState() {
fmt.Println(resp.Err)
return strs
}
strs = strings.Split(resp.String(), "\n")
// 去除头一行说明
if strings.Contains(strs[0], "===") {
strs = strs[1:]
}
// 去除尾部可能存在的空行
if len(strs[len(strs)-1]) < 32 {
strs = strs[:len(strs)-1]
}
return strs
}
func getTodayStr() string {
// 设置上海时区
loc, err := time.LoadLocation("Asia/Shanghai")
if err != nil {
fmt.Println("无法加载时区信息:", err)
return ""
}
now := time.Now().In(loc)
// 格式化日期
return now.Format("20060102")
}

@ -39,4 +39,5 @@ func setRoute(r *gin.Engine) {
// 工具接口
r.GET("/api/tool/v1/voice/list", qatool.GetVoiceTestData)
r.GET("/api/tool/v1/bigdata/query", qatool.GetProjectBigData)
}

Loading…
Cancel
Save