Skip to content

Commit

Permalink
fixed #138 #125
Browse files Browse the repository at this point in the history
  • Loading branch information
rafa0128 committed Apr 4, 2023
1 parent 41cdd73 commit b8a02b9
Show file tree
Hide file tree
Showing 14 changed files with 305 additions and 197 deletions.
23 changes: 13 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<p align="center">
<a>English</a> | <a href="./README.zh.md">中文</a> | <a href="./DocForAndroid.md">DocForAndroid</a>
<a>English</a> | <a href="./README.zh.md">中文</a>
</p>

<p align="center">
Expand All @@ -13,6 +13,7 @@
<p align="center">
<a href="https://pypi.org/project/solox/" target="__blank"><img src="https://img.shields.io/pypi/v/solox" alt="solox preview"></a>
<a href="https://pypistats.org/packages/solox" target="__blank"><img src="https://img.shields.io/pypi/dm/solox"></a>
<a href="https://pypistats.org/packages/solox" target="__blank"><img src="https://img.shields.io/badge/FAQ-%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98-orange"></a>

<br>
</p>
Expand All @@ -26,10 +27,10 @@ We are committed to solving inefficient, cumbersome test execution, and our goal
<img src="https://cdn.nlark.com/yuque/0/2022/png/153412/1662348054846-b0164165-e83a-443e-9a05-8c1f9ddb355f.png?x-oss-process=image%2Fresize%2Cw_1500%2Climit_0" width="100%" >

## Installation
```
1.Python:3.10+ (python3.6+ lower v2.5.3)
2.pip install -U solox
3.pip install -i https://mirrors.ustc.edu.cn/pypi/web/simple -U solox (Recommend)
```shell
1.Python:3.10+ (Python 3.6 3.7 3.8 3.9 Please download a version of solox lower than 2.5.4)
2.pip install -U solox
3.pip install -i https://mirrors.ustc.edu.cn/pypi/web/simple -U solox (China)

notice: If Windows users need to test ios, install and start Itunes
```
Expand All @@ -52,11 +53,11 @@ from solox.public.apm import APM

apm = APM(pkgName='com.bilibili.app.in',deviceId='ca6bd5a5',platform='Android', surfaceview=True)
# apm = APM(pkgName='com.bilibili.app.in', platform='iOS') only supports one device
# surfaceview: false = gfxinfo (Developer - GPU rendering mode - adb shell dumpsys gfxinfo)
# surfaceview: False = gfxinfo (Developer - GPU rendering mode - adb shell dumpsys gfxinfo)

cpu = apm.collectCpu() # %
memory = apm.collectMemory() # MB
flow = apm.collectFlow() # KB
flow = apm.collectFlow(wifi=True) # KB
fps = apm.collectFps() # HZ
battery = apm.collectBattery() # level:% temperature:°C current:mA voltage:mV power:w
gpu = apm.collectGpu() # % only supports ios
Expand All @@ -73,9 +74,9 @@ Windows: start /min python3 -m solox &
```

### Request apm data from api
```
- Android: http://{ip}:{port}/apm/collect?platform=Android&deviceid=ca6bd5a5&pkgname=com.bilibili.app.in&target=cpu
- iOS: http://{ip}:{port}/apm/collect?platform=iOS&pkgname=com.bilibili.app.in&target=cpu
```shell
Android: http://{ip}:{port}/apm/collect?platform=Android&deviceid=ca6bd5a5&pkgname=com.bilibili.app.in&target=cpu
iOS: http://{ip}:{port}/apm/collect?platform=iOS&pkgname=com.bilibili.app.in&target=cpu

target in ['cpu','memory','network','fps','battery']
```
Expand All @@ -84,6 +85,8 @@ target in ['cpu','memory','network','fps','battery']
- 2-devices: test the same app on two different phones
- 2-apps: test two different apps on two phones with the same configuration

notice: only supports android

<img src="https://cdn.nlark.com/yuque/0/2022/png/153412/1662348055024-96e38b5e-d6b4-4a06-8070-0707e2fbcd99.png?x-oss-process=image%2Fresize%2Cw_1500%2Climit_0" width="100%">

## Browser
Expand Down
18 changes: 10 additions & 8 deletions README.zh.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<p align="center">
<a>中文</a> | <a href="./README.md">English</a> | <a href="./DocForAndroid.md">DocForAndroid</a>
<a>中文</a> | <a href="./README.md">English</a>
</p>

<p align="center">
Expand All @@ -26,8 +26,8 @@ SoloX - Android/iOS性能数据实时采集工具。
<img src="https://cdn.nlark.com/yuque/0/2022/png/153412/1662348054846-b0164165-e83a-443e-9a05-8c1f9ddb355f.png?x-oss-process=image%2Fresize%2Cw_1500%2Climit_0" width="100%" >

## 安装
```
1.Python:3.6+ (python3.6+ 小于v2.5.3)
```shell
1.Python:3.10+ (Python 3.6 3.7 3.8 3.9 请下载低于2.5.4的版本)
2.pip install -U solox
3.pip install -i https://mirrors.ustc.edu.cn/pypi/web/simple -U solox (在国内推荐使用镜像下载)

Expand All @@ -52,10 +52,10 @@ from solox.public.apm import APM

apm = APM(pkgName='com.bilibili.app.in',deviceId='ca6bd5a5',platform='Android', surfaceview=True)
# apm = APM(pkgName='com.bilibili.app.in', platform='iOS') only supports one device
# surfaceview: false = gfxinfo (手机开发者-GPU呈现模式- adb shell dumpsys gfxinfo)
# surfaceview: False = gfxinfo (手机开发者-GPU呈现模式- adb shell dumpsys gfxinfo)
cpu = apm.collectCpu() # %
memory = apm.collectMemory() # MB
flow = apm.collectFlow() # KB
flow = apm.collectFlow(wifi=True) # KB
fps = apm.collectFps() # HZ
battery = apm.collectBattery() # level:% temperature:°C current:mA voltage:mV power:w
gpu = apm.collectGpu() # % only supports ios
Expand All @@ -72,9 +72,9 @@ Windows: start /min python3 -m solox &
```

### 2.通过api请求性能数据
```
- Android: http://{ip}:{port}/apm/collect?platform=Android&deviceid=ca6bd5a5&pkgname=com.bilibili.app.in&target=cpu
- iOS: http://{ip}:{port}/apm/collect?platform=iOS&pkgname=com.bilibili.app.in&target=cpu
```shell
Android: http://{ip}:{port}/apm/collect?platform=Android&deviceid=ca6bd5a5&pkgname=com.bilibili.app.in&target=cpu
iOS: http://{ip}:{port}/apm/collect?platform=iOS&pkgname=com.bilibili.app.in&target=cpu

target in ['cpu','memory','network','fps','battery']
```
Expand All @@ -83,6 +83,8 @@ target in ['cpu','memory','network','fps','battery']
- 2-devices: 在两部不同的手机上测试同一个应用
- 2-apps: 在具有相同配置的两部手机上测试两个不同的应用程序

注意: 目前只支持安卓

<img src="https://cdn.nlark.com/yuque/0/2022/png/153412/1662348055024-96e38b5e-d6b4-4a06-8070-0707e2fbcd99.png?x-oss-process=image%2Fresize%2Cw_1500%2Climit_0" width="100%">

## 推荐浏览器
Expand Down
2 changes: 1 addition & 1 deletion solox/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

from __future__ import absolute_import

__version__ = '2.5.5'
__version__ = '2.5.6'
20 changes: 12 additions & 8 deletions solox/debug.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
from flask_socketio import SocketIO, disconnect
from flask import Flask
import fire as fire
import signal


app = Flask(__name__, template_folder='templates', static_folder='static')
app.register_blueprint(api)
Expand Down Expand Up @@ -141,7 +143,7 @@ def openUrl(host: str, port: int):
"""
flag = True
while flag:
logger.info('start solox server...')
logger.info('start solox server')
flag = getServerStatus(host, port)
webbrowser.open(f'http://{host}:{port}/?platform=Android&lan=en', new=2)
logger.info(f'Running on http://{host}:{port}/?platform=Android&lan=en (Press CTRL+C to quit)')
Expand All @@ -155,6 +157,7 @@ def startServer(host: str, port: int):
:return:
"""
try:
logger.info(f'Running on http://{host}:{port}/?platform=Android&lan=en (Press CTRL+C to quit)')
socketio.run(app, host=host, debug=False, port=port)
except Exception:
sys.exit(0)
Expand All @@ -169,15 +172,16 @@ def main(host=_hostIP(), port=50003):
try:
checkPyVer()
listeningPort(port=port)
pool = multiprocessing.Pool(processes=2)
pool.apply_async(startServer, (host, port))
pool.apply_async(openUrl, (host, port))
pool.close()
pool.join()
startServer(host, port)
# pool = multiprocessing.Pool(processes=2)
# pool.apply_async(startServer, (host, port))
# pool.apply_async(openUrl, (host, port))
# pool.close()
# pool.join()
except Exception:
pass
sys.exit(0)
except KeyboardInterrupt:
logger.info('stop solox success')

if __name__ == '__main__':
fire.Fire(main)
fire.Fire(main)
12 changes: 11 additions & 1 deletion solox/public/apm.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,16 @@ def getAndroidNet(self, wifi=True):
recNum = round(float(recNum_final - recNum_pre), 2)
return sendNum, recNum

def setAndroidNet(self, wifi=True):
net = 'wlan0' if wifi else 'rmnet0'
pid = d.getPid(pkgName=self.pkgName, deviceId=self.deviceId)
cmd = f'cat /proc/{pid}/net/dev |{d.filterType()} {net}'
output_pre = adb.shell(cmd=cmd, deviceId=self.deviceId)
m = re.search(r'{}:\s*(\d+)\s*\d+\s*\d+\s*\d+\s*\d+\s*\d+\s*\d+\s*\d+\s*(\d+)'.format(net), output_pre)
sendNum = round(float(float(m.group(2)) / 1024), 2)
recNum = round(float(float(m.group(1)) / 1024), 2)
return sendNum, recNum


def getiOSNet(self):
"""Get iOS upflow and downflow data"""
Expand Down Expand Up @@ -333,7 +343,7 @@ def __init__(self, pkgName, deviceId='', platform=Platform.Android, surfaceview=
self.deviceId = deviceId
self.platform = platform
self.surfaceview = surfaceview
d.devicesCheck(pf=self.platform, id=self.deviceId, pkg=self.pkgName)
d.devicesCheck(platform=self.platform, deviceid=self.deviceId, pkgname=self.pkgName)

def collectCpu(self):
_cpu = CPU(self.pkgName, self.deviceId, self.platform)
Expand Down
114 changes: 69 additions & 45 deletions solox/public/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import time
import requests
from logzero import logger
from flask import request
from solox.public.adb import adb
from tqdm import tqdm
import traceback
Expand Down Expand Up @@ -176,16 +175,17 @@ def export_excel(self, platform, scene):
ws1.write(0,1,'Value')
row = 1 #start row
col = 0 #start col
f = open(f'{self.report_dir}/{scene}/{name}.log','r',encoding='utf-8')
for lines in f:
target = lines.split('=')
k += 1
for i in range(len(target)):
ws1.write(row, col ,target[i])
col += 1
row += 1
col = 0
wb.save(f'{scene}.xls') # xxx.xls
if os.path.exists(f'{self.report_dir}/{scene}/{name}.log'):
f = open(f'{self.report_dir}/{scene}/{name}.log','r',encoding='utf-8')
for lines in f:
target = lines.split('=')
k += 1
for i in range(len(target)):
ws1.write(row, col ,target[i])
col += 1
row += 1
col = 0
wb.save(f'{scene}.xls')

def get_repordir(self):
report_dir = os.path.join(os.getcwd(), 'report')
Expand All @@ -194,16 +194,32 @@ def get_repordir(self):
return report_dir

def create_file(self, filename, content=''):
if not os.path.exists(f'{self.report_dir}'):
os.mkdir(f'{self.report_dir}')
with open(f'{self.report_dir}/{filename}', 'a+', encoding="utf-8") as file:
if not os.path.exists(self.report_dir):
os.mkdir(self.report_dir)
with open(os.path.join(self.report_dir, filename), 'a+', encoding="utf-8") as file:
file.write(content)

def add_log(self, path, log_time, value):
if value >= 0:
with open(path, 'a+', encoding="utf-8") as file:
file.write(f'{log_time}={str(value)}' + '\n')


def record_net(self, type, send , recv):
net_dict = {}
match(type):
case 'pre':
net_dict['send'] = send
net_dict['recv'] = recv
content = json.dumps(net_dict)
self.create_file(filename='pre_net.json', content=content)
case 'end':
net_dict['send'] = send
net_dict['recv'] = recv
content = json.dumps(net_dict)
self.create_file(filename='end_net.json', content=content)
case _:
logger.error('record network data failed')

def make_report(self, app, devices, platform='Android', model='normal'):
current_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
result_dict = {
Expand All @@ -216,7 +232,7 @@ def make_report(self, app, devices, platform='Android', model='normal'):
}
content = json.dumps(result_dict)
self.create_file(filename='result.json', content=content)
report_new_dir = f'{self.report_dir}/{self.fileroot}'
report_new_dir = os.path.join(self.report_dir, self.fileroot)
if not os.path.exists(report_new_dir):
os.mkdir(report_new_dir)

Expand All @@ -237,22 +253,24 @@ def readLog(self, scene, filename):
"""Read apmlog file data"""
log_data_list = []
target_data_list = []
f = open(f'{self.report_dir}/{scene}/{filename}', "r")
lines = f.readlines()
for line in lines:
if isinstance(line.split('=')[1].strip(), int):
log_data_list.append({
"x": line.split('=')[0].strip(),
"y": int(line.split('=')[1].strip())
})
target_data_list.append(int(line.split('=')[1].strip()))
else:
log_data_list.append({
"x": line.split('=')[0].strip(),
"y": float(line.split('=')[1].strip())
})
target_data_list.append(float(line.split('=')[1].strip()))
if os.path.exists(os.path.join(self.report_dir,scene,filename)):
f = open(os.path.join(self.report_dir,scene,filename), "r")
lines = f.readlines()
for line in lines:
if isinstance(line.split('=')[1].strip(), int):
log_data_list.append({
"x": line.split('=')[0].strip(),
"y": int(line.split('=')[1].strip())
})
target_data_list.append(int(line.split('=')[1].strip()))
else:
log_data_list.append({
"x": line.split('=')[0].strip(),
"y": float(line.split('=')[1].strip())
})
target_data_list.append(float(line.split('=')[1].strip()))
return log_data_list, target_data_list


def getCpuLog(self, platform, scene):
targetDic = {}
Expand Down Expand Up @@ -363,14 +381,16 @@ def _setAndroidPerfs(self, scene):
fpsAvg = f'{int(sum(fpsData) / len(fpsData))}HZ/s'

jankData = self.readLog(scene=scene, filename=f'jank.log')[1]
jankAvg = f'{int(sum(jankData) / len(jankData))}'

flowSendData = self.readLog(scene=scene, filename=f'upflow.log')[1]
flowSend = f'{round(float(sum(flowSendData) / 1024), 2)}MB'

flowRecvData = self.readLog(scene=scene, filename=f'downflow.log')[1]
flowRecv = f'{round(float(sum(flowRecvData) / 1024), 2)}MB'
jankAvg = f'{int(sum(jankData))}'

f_pre = open(os.path.join(self.report_dir,scene,'pre_net.json'))
f_end = open(os.path.join(self.report_dir,scene,'end_net.json'))
json_pre = json.loads(f_pre.read())
json_end = json.loads(f_end.read())
send = json_end['send'] - json_pre['send']
recv = json_end['recv'] - json_pre['recv']
flowSend = f'{round(float(send / 1024), 2)}MB'
flowRecv = f'{round(float(recv / 1024), 2)}MB'
apm_dict = {}
apm_dict['cpuAppRate'] = cpuAppRate
apm_dict['cpuSystemRate'] = cpuSystemRate
Expand Down Expand Up @@ -470,21 +490,25 @@ def _setpkPerfs(self, scene):


class Method:

def _request(self, request, object):

@classmethod
def _request(cls, request, object):
match(request.method):
case 'POST':
return request.form[object]
case 'GET':
return request.args[object]
case _:
raise Exception('request method error')

def _setValue(self, value):

@classmethod
def _setValue(cls, value, default = 0):
try:
result = value
except:
result = 0
except ZeroDivisionError :
result = default
except Exception:
result = default
return result

class Install:
Expand Down Expand Up @@ -533,4 +557,4 @@ def installIPA(self, path):
os.remove(path)
return True, result
else:
return False, result
return False, result
Loading

0 comments on commit b8a02b9

Please sign in to comment.