上周入职新公司,公司的业务有做sdk。遇到反馈的bug量直线上升,每天bug量达到了上千个。我得到的第一个任务是对这些bug进行系统的管理及分析。
参考《app研发录》提供的思路,是将所有的bug存入到数据库中进行管理。下面是对该任务记录:
已知条件:
1.app将报的所有的bug信息存储在amazon的aws上面的。
2.有一台centos服务器。
3.错误信息的文件名中包含国家,sdk的版本,手机品牌等信息通过"_"链接。
任务整体设计思路:
- 配置shadowsocks,因为从amazon的aws中获取数据,需要翻墙。
- 使用python写一个脚本,每天自动的从服务器抓取错误信息到本地.
- 将包含有我们公司信息(错误信息中包含我们公司包名)的错误信息存入到数据库。
- 通过sql语句的强大查询功能对bug进行分析。
- 结果:通过几句简单的sql语句,对7490个进行分析,得到了如下信息:
4.1:bug类型一个有1299个
4.2:其中内存溢出有1072个。并且找到了具体的出错原因。
4.3: 产生内存溢出所涉及到的国家29个,一共有52个国家。
4.4:参数bug涉及的到机型一共494种。

任务实施步骤:
- 在Centos中装mysql数据库,Shadowsocks,因为shadowsocks最低需要python3.0以上,而centos自带的python版本是2.7.5,所以额外的需要装python3.5。
- 设计的表结构:
+-------------+----------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+----------------+------+-----+---------+-------+
| ID | varchar(20) | YES | | NULL | |
| USER_CONTRY | varchar(100) | YES | | NULL | |
| PHONE_TYPE | varchar(500) | YES | | NULL | |
| SDK_VERSION | varchar(500) | YES | | NULL | |
| ANDROID_ID | varchar(100) | YES | | NULL | |
| BUG_TYPE | varchar(1000) | YES | | NULL | |
| BUG_DETAIL | text | YES | | NULL | |
| BUG_COUNT | varchar(10000) | YES | | NULL | |
| BUG_STATUS | varchar(1000) | YES | | NULL | |
| REMARK | varchar(2000) | YES | | NULL | |
| BUG_TIME | varchar(100) | YES | | NULL | |
| APP_NAME | varchar(100) | YES | | NULL | |
+-------------+----------------+------+-----+---------+-------+
- 我将抓取错误文件到本地和将错误文件信息写进数据库分成了两个任务,原因是我在插入数据库的过程中有异常,防止一个任务中断,影响到另一个任务。同时,我将两个脚本做成了定时任务,每天定时执行。
将在amazon的aws上的bug文件抓取到本地的脚本:
#/usr/bin/python
# _*_ coding: UTF-8 _*_
import time
import datetime
import os
def autoPull(n):
while True:
print("----------------------------------------")
time.sleep(n)
currTime = time.strftime("%-H:%-M", time.localtime())
if currTime == "9:21":
print("shijiandaole....")
pullFile()
else:
print("auto pull file ,current time = %s"%currTime)
#getPackageName()
#timer(10)
def pullErrFile(time,packageName,fileName):
line = "aws s3 sync s3://sdk-crash-1/%s/%s %s"%(time,packageName,fileName)
print(line)
os.system(line)
#pullErrFile('2017-7-22')
def generateFileName(packagename,time):
return "%s__%s"%(packagename,time)
def generateTime():
last_date = datetime.date.today()
return last_date.strftime("%Y-%-m-%-d")
#print(generateFileName("test"))
def pullFile():
packages = set(['photo.studio.editor.selfie.camera','com.yiba.baidu.wifi','com.xvideostudio.videoeditorlite','com.necta.wifimousefree','com.infreewifi.cct','com.dianxinos.dxbs','com.yiba.sdk', 'com.yiba.sharewe.lite.activity', 'com.baidu.app', 'com.yiba.baidu.wifi'])
for name in packages:
print("name = %s"%name)
pullErrFile(generateTime(),name,generateFileName(name,generateTime()))
#pullErrFile("2017-4-26",name,generateFileName(name,"2017-4-26"))
#pullFile()
autoPull(60)
print(generateTime())
自动插入数据库的python代码:
设计思路:
遍历
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import os
from random import Random
import time
import pymysql
import datetime
print("|--------------------------------------------------------|")
print("|------------------------welcome-------------------------|")
print("|--------------------------------------------------------|")
def random_str(randomlength=8):
str = ''
chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789'
length = len(chars) - 1
random = Random()
for i in range(randomlength):
str += chars[random.randint(0,length)]
return str
# insert data to table
def insert(id,user_county,phone_type,sdk_version,android_id,bug_type,bug_detail,bug_count,bug_status,remark,bug_time,app_name):
# get db obj
db = pymysql.connect("localhost","root","root","bugDB")
cursor = db.cursor()
cursor.execute("SELECT VERSION()")
data = cursor.fetchone()
print("To prepare insert")
sql = "INSERT INTO bugInfo VALUES('%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s')"%(id,user_county,phone_type,sdk_version,android_id,bug_type,bug_detail,bug_count,bug_status,remark,bug_time,app_name)
try:
cursor.execute(sql)
db.commit()
print('insert successed')
except Exception as e:
db.rollback()
print('insert failed',e)
print(bug_detail)
db.close()
# insert data to table
def insertAll(id,user_county,phone_type,sdk_version,android_id,bug_type,bug_detail,bug_count,bug_status,remark,bug_time,app_name):
# get db obj
db = pymysql.connect("localhost","root","root","bugDB")
cursor = db.cursor()
cursor.execute("SELECT VERSION()")
data = cursor.fetchone()
print("To prepare insert")
sql = "INSERT INTO allBug VALUES('%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s')"%(id,user_county,phone_type,sdk_version,android_id,bug_type,bug_detail,bug_count,bug_status,remark,bug_time,app_name)
try:
cursor.execute(sql)
db.commit()
print('insert successed')
except Exception as e:
db.rollback()
print('insert failed',e)
print(bug_detail)
db.close()
#insert('3','usa','hauwei','2.2.1','adbaec321ea32','outofmery','outofmery','23','fixed','remark','100230302','com.yh.xxx')
def parseFile(path,package,type):
try:
files = os.listdir(path)
count = 0
print(type)
s = []
for file in files:
print('deal ....')
strName = file+""
res = strName.split('_')
countryId = res[0]
phoneType = res[1]
sdkVersion = res[2]
deviceId = res[3]
bugTime = res[4].split('.')[0]
count+=1
bug_type = " "
if not os.path.isdir(file):
f = open(path+"/"+file);
iter_f = iter(f);
bug_detail = " \n"
for line in iter_f:
bug_detail = bug_detail + line
if type == "all":
bug_detail = bug_detail.replace("\'",'')
insertAll(random_str(),countryId,phoneType,sdkVersion,deviceId,bug_type,bug_detail,'','unfix','',bugTime,package)
else:
if 'yiba' in bug_detail:
bug_detail=bug_detail.replace("\'",'')
insert(random_str(),countryId,phoneType,sdkVersion,deviceId,bug_type,bug_detail,'','unfix','',bugTime,package)
print(count)
except Exception as e:
print("has an exception= %s"%e)
#path = input("please input file path:")
#package = input("please input app name:")
#type = input("please input type:")
#parseFile(path,package,type)
def generateFileName(packagename,time):
return "%s__%s"%(packagename,time)
def generateTime():
last_date = datetime.date.today()
return last_date.strftime("%Y-%-m-%-d")
#print(generateFileName("test"))
def insertToMysql(type):
packages = set(['photo.studio.editor.selfie.camera','com.yiba.baidu.wifi','com.xvideostudio.videoeditorlite','com.necta.wifimousefree','com.infreewifi.cct','com.dianxinos.dxbs','com.yiba.sdk', 'com.yiba.sharewe.lite.activity', 'com.baidu.app', 'com.yiba.baidu.wifi'])
for name in packages:
print("name = %s"%name)
#path = "/root/bugManageSystem/%s"%generateFileName(name,generateTime())
path = "/root/bugManageSystem/%s"%generateFileName(name,"2017-4-26")
parseFile(path,name,type)
#insertToMysql("")
def autoInsert(n):
while True:
time.sleep(n)
currTime = time.strftime("%-H:%-M", time.localtime())
if currTime == "9:35":
print("shijiandaole....")
insertToMysql("")
else:
print("insert to mysql ,current time = %s"%currTime)
autoInsert(60)
#insertToMysql("")
废话:刚接到这个任务的时候,我想着是写一个android客户端。后面同事提示做成一个pc的客户端。一时才反应过来这个好像写成android客户端还真不合适。
总结:
- 对整个任务进行了分析后,对需要用到的知识点一一罗列,然后一个一个的知识点进行学习。对各个知识点的掌握很快,时间主要花在了出现的各种各样从未遇到的bug,还好有google。
- 对linux下的命令和对 对vim 编辑器有一定的熟悉间接的帮助了我快速完成这次任务。
- python的代码有些写的有点操蛋,比如操作数据库没有写成单例,两个文件中有相同的函数没有进行整理等。后面再慢慢优化。
网友评论