【nodejs】SWQA平台缺陷模块数据处理

来源:互联网 发布:php框架学习 编辑:程序博客网 时间:2024/05/03 02:28

最近重构数据平台的BUG模块,由于不熟悉,对于一些数据的处理折腾了一小段时间

数据平台的BUG模块主要是从jira平台中请求获取数据,接口文档参考jira的官方文档:
https://docs.atlassian.com/jira/REST/cloud/#api/2/search-search

缺陷状态及类型

  • 新增缺陷

缺陷类型(bug、bug-上版本漏测、bug-与需求不符、bug-未自测、bug-需求未更新、tracking)
缺陷严重程度(致命、严重、一般、次要)

  • 关闭缺陷

缺陷关闭类型(不能复现、局限性、已解决、无效bug、未处理、设计如此、重复问题)

  • 打回缺陷

  • 遗留缺陷

缺陷类型(bug、bug-上版本漏测、bug-与需求不符、bug-未自测、bug-需求未更新、tracking)
缺陷严重程度(致命、严重、一般、次要)
缺陷状态(新建、重新打开、测试中、开发中、待挂起、被拒绝)
缺陷优先级(Highest、High、Medium、Low、Lowest)
出现频率(总是、无法重现、有时、没有试验、随机)
缺陷模块
缺陷经办人

以上为需要统计的缺陷的状态和相关的数据,缺陷的类型和状态梳理OK后,研究一下请求的语句

请求的语句

使用的url为 /rest/api/2/search method:get
请求参数为 sql 语句

关于请求不同类型的BUG,如果不分项目,一次性的全部请求后再次解析,目前的BUG数量为差不多1w条,而且这个数值是增长的趋势,故不宜将所有数据获取然后解析,因此分开四种状态,用不同的sql条件去获取BUG

PS:这里说明一下,原本因为打回和关闭缺陷在原先Jira平台中并没有默认的字段,将配置了“缺陷打回时间”、“缺陷关闭时间”和“缺陷关闭类型”等字段后,即可进行搜索,避免了原来的得到新增和遗留问题后计算获得关闭缺陷的无奈之举

新增、关闭、打回和遗留缺陷分别进行查询,因为jira平台中部分缺陷是不需要进行计算和查询,故查询时只进行了部分项目的查询,将每个sql语句进行了封装

var sqlArr = function (DateStart,DateLast,projectApp) {    var param = {        sqlinfo:            [                {                    type:"new",                    sql:newbugSql(DateStart,DateLast,projectApp)                },                {                    type:"close",                    sql:closebugSql(DateStart,DateLast,projectApp)                },                {                    type:"reopen",                    sql:reopenbugSql(DateStart,DateLast,projectApp)                },                {                    type:"legacy",                    sql:legacybugSql(projectApp)                }            ],    }    return param;}

数据解析

现在看一下请求接口获得的数据

比如现在获取的是某一个项目某一天创建的缺陷,请求jira后响应的数据为:

{ expand: 'schema,names',  startAt: 0,  maxResults: 1000,  total: 8,  issues:    [ { expand: 'operations,versionedRepresentations,editmeta,changelog,renderedFields',       id: '115562',       self: 'https://jira.xxxx.com/rest/api/2/issue/115562',       key: 'CARE-2126',       fields: [Object] },     { expand: 'operations,versionedRepresentations,editmeta,changelog,renderedFields',       id: '115449',       self: 'https://jira.xxxx.com/rest/api/2/issue/115449',       key: 'CARE-2122',       fields: [Object] },     { expand: 'operations,versionedRepresentations,editmeta,changelog,renderedFields',       id: '115359',       self: 'https://jira.xxxx.com/rest/api/2/issue/115359',       key: 'CARE-2119',       fields: [Object] } ] }

现在解析其中的issues 中一个数据,得到的数据:

  { expand: 'operations,versionedRepresentations,editmeta,changelog,renderedFields',    id: '107673',    self: 'https://jira.xxxx.com/rest/api/2/issue/107673',    key: 'REM-1169',    fields:      { fixVersions: [],       customfield_11200: null,       resolution: null,       customfield_10509: null,       lastViewed: null,       priority: [Object],       customfield_10100: null,       labels: [Object],       customfield_10456: '功能缺陷,并没有实行上面模块的更新',       customfield_10457: null,       aggregatetimeoriginalestimate: null,       timeestimate: null,       versions: [Object],       issuelinks: [Object],       assignee: [Object],       status: [Object],       components: [Object],       customfield_10601: null,       customfield_10602: '2017-02-21T12:12:00.000+0800',       customfield_10448: null,       customfield_10603: null,       aggregatetimeestimate: null,       creator: [Object],       subtasks: [],       reporter: [Object],       customfield_10440: null,       aggregateprogress: [Object],       customfield_11006: 'win7 64 中文专业,Chrome56.0.2924.87',       customfield_10434: null,       customfield_10435: null,       customfield_11007: [Object],       customfield_10436: null,       customfield_10315: null,       customfield_11008: [Object],       votes: [Object],       issuetype: [Object],       timespent: null,       project: [Object],       customfield_11000: null,       customfield_11117: '无',       workratio: -1,       watches: [Object],       created: '2017-02-21T12:12:56.000+0800',       customfield_10419: null,       updated: '2017-02-28T15:16:28.000+0800',       timeoriginalestimate: null,       description: '管理员设置:修改管理员名称后,学校信息列表中的管理员名称不会实时刷新',       customfield_10010: null,       customfield_10011: null,       customfield_11100: null,       customfield_11101: [Object],       customfield_11102: [Object],       customfield_10404: [Object],       customfield_10009: '0|i0eaq8:',       customfield_10409: '[3788554] 功能缺陷,都已修复咯',       summary: '页面刷新:两个不会实时刷新的问题',       customfield_11213: null,       customfield_10004: null,       customfield_11214: null,       customfield_10511: null,       customfield_11204: null,       customfield_11205: null,       environment: null,       customfield_11206: null,       customfield_10514: null,       duedate: null,       customfield_10517: null } },

根据解析的数据,将需要的信息组合成对象:

var bugdata = {      thedate:collectdate,      type:"",      projectgroup:"",      project:item.fields.project.name,          //缺项所在项目名称      abb:item.fields.watches.self.split("/")[7],     //缺陷编号缩写      creator:item.fields.creator.displayName,        //缺陷创建者      createdtime:item.fields.created,      //缺陷创建时间      assignee:item.fields.assignee.displayName,            //缺陷经办人      affectversions:item.fields.versions[0].name,     //缺陷影响版本      fixversions:item.fields.fixVersions[0].name,         //缺陷解决版本      status:item.fields.status.name,                 //缺陷状态      statusCategory:item.fields.status.statusCategory.name,  //状态类别      testplatform:item.fields.status.customfield_11006,     //测试平台      resolution:item.fields.resolution.name,           //解决结果      components:item.fields.components[0].name,         //缺陷所属软件模块      labels:item.fields.customfield_11004.value,       //缺陷标签      bugtype:item.fields.labels,    //缺陷类型      closetype:item.fields.customfield_11007.value,   //缺陷关闭类型      severity:item.fields.customfield_11008.value,   //缺陷严重程度      priority:item.fields.priority.name,     //缺陷优先级      frequency:item.fields.customfield_10413.value,  //缺陷出现频率      closeddate:item.fields.customfield_11210,   //缺陷关闭时间      reopendate:item.fields.customfield_11211,   //缺陷打回时间 }

当然,在处理数据时,发现有些缺陷的某些数据可能是null,故需要进行判断后进行处理

写入数据库

现在的机制是,每天早上7点10分从数据库中获取昨天一天的数据,发现每天的遗留BUG数据约为1000条,3个月即可达到10w的数量级,如果已写在数据库中的遗留BUG只进行Update处理,那么一个遗留BUG的状态、优先级和经办人等信息保存相对比较困难,故不采用这样的方式

由于仅仅是遗留的问题数量级比较大,故将遗留问题在数据库中存为一个表,另外三种状态存为另外一个表中

读取数据库

因为前段不同的模块需要展示不同维度的BUG数据,而且各个项目还需要每个开发的各个维度的BUG数据的情况,故如何处理数据并且将什么数据传给前端

在读取数据库的数据时,如果没需要一个维度的数据就进行一次查询,这样对于数据库的请求次数较为频繁。故使用LEFT JOIN 的方式将查询表进行拼接

如这样的数据库查询语句:

SELECT a.projectgroup,a.project,IFNULL(a.legacy_all,0) as legacy_all,IFNULL(b.legacy_status_build,0) as legacy_status_build,IFNULL(c.legacy_status_reopen,0) as legacy_status_reopen from (SELECT projectgroup, project,count(*)as legacy_all from dataplatform_bugdata_legacy_org where thedate = '2017-03-13' and project = 'SR' group by projectgroup,project)a LEFT JOIN(SELECT project, count(*) as legacy_status_build from dataplatform_bugdata_legacy_org where  thedate = '2017-03-13' and project = 'SR' and statuss='新建' group by project,statuss)b ON b.project =  b.project LEFT JOIN(SELECT project, count(*) as legacy_status_reopen from dataplatform_bugdata_legacy_org where  thedate = '2017-03-13' and project = 'SR' and statuss='重新打开' group by project,statuss)c ON c.project =  c.project

查询的表为:

这里写图片描述

程序请求获取的数据格式为:

RowDataPacket {    projectgroup: '项目组一',    project: 'SR',    legacy_all: 86,    legacy_status_build: 54,    legacy_status_reopen: 6,    legacy_status_testing: 20,    legacy_status_develop: 0,    legacy_status_suspend: 6,    legacy_status_reject: 0,    legacy_severity_A: 2,    legacy_severity_B: 10,    legacy_severity_C: 65,    legacy_severity_D: 0 }

这样json left 的方式进行表拼接有个问题,目前当个查询的时长为0.001s的级别,但是如果数据库的数据量较大时,这样的方式查询耗时较大,数据库每个表在一个时刻点只处理一个事件查询,这样会造成堵塞部分查询超时失败

开始想着怎么把这些数据拼凑在一起直接传给前端,故使用Map对数据进行组合

/** * 按照map键值对组合数据 * @param bugDBsql * @param callback */var bugdata = function (bugDBsql,callback) {    operateDB.operateDB(bugDBsql,(err,data)=>{        var bugmap  = new Map();        for(var item of data){            if(bugmap.get(item.project)==null){                bugmap.set(item.project,[])                bugmap.get(item.project).push(item);            }else{                bugmap.get(item.project).push(item);            }        }        callback(bugmap);    })}

此时数据格式为:

{  '项目一' => [ RowDataPacket {    projectgroup: '项目组一',    project: '项目一',    legacy_all: 76,    legacy_status_build: 10,    legacy_status_reopen: 8,    legacy_status_testing: 22,    legacy_status_develop: 3,    legacy_status_suspend: 31,    legacy_status_reject: 2,    legacy_severity_A: 0,    legacy_severity_B: 9,    legacy_severity_C: 52,    legacy_severity_D: 5 } ],  '项目二' => [ RowDataPacket {    projectgroup: '项目组二',    project: '项目二',    legacy_all: 26,    legacy_status_build: 20,    legacy_status_reopen: 0,    legacy_status_testing: 5,    legacy_status_develop: 1,    legacy_status_suspend: 0,    legacy_status_reject: 0,    legacy_severity_A: 0,    legacy_severity_B: 2,    legacy_severity_C: 5,    legacy_severity_D: 0 } ],  '项目三' => [ RowDataPacket {    projectgroup: '项目组三',    project: '项目三',    legacy_all: 62,    legacy_status_build: 27,    legacy_status_reopen: 9,    legacy_status_testing: 8,    legacy_status_develop: 6,    legacy_status_suspend: 12,    legacy_status_reject: 0,    legacy_severity_A: 2,    legacy_severity_B: 8,    legacy_severity_C: 16,    legacy_severity_D: 0 } ],    legacy_severity_D: 15 } ],  '项目四' => [ RowDataPacket {    projectgroup: '项目组四',    project: '项目四',    legacy_all: 86,    legacy_status_build: 54,    legacy_status_reopen: 6,    legacy_status_testing: 20,    legacy_status_develop: 0,    legacy_status_suspend: 6,    legacy_status_reject: 0,    legacy_severity_A: 2,    legacy_severity_B: 10,    legacy_severity_C: 65,    legacy_severity_D: 0 } ],  '项目五' => [ RowDataPacket {    projectgroup: '项目组五',    project: '项目五',    legacy_all: 19,    legacy_status_build: 7,    legacy_status_reopen: 1,    legacy_status_testing: 5,    legacy_status_develop: 0,    legacy_status_suspend: 6,    legacy_status_reject: 0,    legacy_severity_A: 0,    legacy_severity_B: 6,    legacy_severity_C: 12,    legacy_severity_D: 0 } ] }

感觉这个数据已经完整的组成传给了前端,但是问题来了,这样的数据格式对于前端真的是OK的么?

开始想着的是需要哪个数据直接这样的方式获取:

data.get('item.project').legacy_all

但是问题来了,这个是分为新增、关闭、打回和遗留四个模块,前端数据处理也比较麻烦,而且前端的数据的格式应该是这样的(前期没有确认前端的数据什么方式比较好,这个坑了)

其实给前端的数据格式以数组的方式即可

这里写图片描述

好吧,这个时候将数据处理成相应的格式

解决的几个比较low的数据处理的问题

  • 对象中增加一组键值
var a = { projectgroup: '项目组二', project: '项目二', reopen_all: 1 }a["abc"] = 1;console.log(a)
  • 多个回调数据怎么整合处理

使用async.series的方式进行 done(error,null) 进行组合

  • 数据组合

在数据组合过程中没有母表,如果创建一个表的话有一大串的数据量,因为只要该项目存在即有遗留的BUG,故将遗留问题这个做为基表,将其他数据加入其中

for(var item_newbug of data.newbug){            for(var item_legacybug_last of data.legacybug_last){                if(item_legacybug_last.project == item_newbug.project){                    item_legacybug_last["new_all"] = item_newbug.new_all;                    item_legacybug_last["new_type_bug"] = item_newbug.new_type_bug;                    item_legacybug_last["new_type_tracking"] = item_newbug.new_type_tracking;                    item_legacybug_last["new_severity_A"] = item_newbug.new_severity_A;                    item_legacybug_last["new_severity_B"] = item_newbug.new_severity_B;                    item_legacybug_last["new_severity_C"] = item_newbug.new_severity_C;                    item_legacybug_last["new_severity_D"] = item_newbug.new_severity_D;                }            }        }

如果不存在新增问题这个选项时,将该项目所有的新增对象置为0

if(item_legacybug_last.new_all==null){                item_legacybug_last["new_all"] = 0;                item_legacybug_last["new_type_bug"] = 0;                item_legacybug_last["new_type_tracking"] = 0;                item_legacybug_last["new_severity_A"] = 0;                item_legacybug_last["new_severity_B"] = 0;                item_legacybug_last["new_severity_C"] = 0;                item_legacybug_last["new_severity_D"] = 0;            }

这样就按照既定的格式完成了数据获取

0 0