微信小程序调试日志实时上报

开发上遇到一些问题我们需要拿到真机上的数据,自己我们使用 vConsole 也可以,需要其他人提供可能就存在一些复杂性了。且适当的日志上报也可以监控出一些非 100% 复现的问题,比如前几天我们和另外一个小程序对接,那边传的参数一定概率存在单个为 null 或 全部为 null 的情况,通过查阅日志可以一定的定位问题。

微信小程序本身就提供了日志功能,在使用过程中发现日志存在非固定的延时,非官方文档所说离开页面或小程序则进行上报;而使用阿里云、腾讯云等云厂商的日志产品存在一定的学习、费用成本,所以最近写了一个比较简单的,因实时所以不适合使用人数过多,大概流程是把小程序发过来的内容整理然后写入文件,然后使用 tail -f filename 进行实时查看。

PHP 代码:

index.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?php

if($_SERVER['REQUEST_METHOD'] !== 'POST') {
echo '不支持当前请求类型';
exit();
}

$data = $_POST;

$filepath = __DIR__ . '/logs/' . $data['app_id'] . '-' . date('Ymd') . '.log';

$content = '---------------------------------------------------
APPID: ' . $data['app_id'] . ' | 版本:' . $data['app_env_version'] . ' | 场景:' . $data['app_scene'] . ' | 时间:' . date('Y-m-d H:i:s') . '
页面路径:' . $data['page_route'] . ' | 页面参数:' . $data['page_options'] . "\n";

$data['openid'] = 'hongfs';

if(isset($data['openid'])) {
$content .= 'openid:' . $data['openid'] . "\n";
}

$content .= '数据:' . $data['data_key'] . ' ' . ($data['data_content'] !== 'null' ? $data['data_content'] : '');

file_put_contents($filepath, $content . PHP_EOL, FILE_APPEND);

?>

请确保当前项目根目录下存在 logs 文件夹且有文件创建、写入权限。


小程序代码:

utils\log.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
var openid = null;

const account_info = wx.getAccountInfoSync().miniProgram;

const enter_options = wx.getEnterOptionsSync();

/**
* 日志上报
*
* @param {String} [key] - 键值(标识)
* @param {Object} [data] - 主要日志内容
*/
const log = (key, data = null) => {
// 禁止正式版上报
// if(account_info.envVersion === 'release') return;

const param = {
app_id: account_info.appId, // 小程序 APPID
app_env_version: account_info.envVersion, // 小程序环境,例如 开发版、体验版。
app_scene: enter_options.scene, // 进入的场景 ID
};

if(openid) {
param['openid'] = openid;
} else {
// 可以提交当前用户的识别 ID 方便排查。
openid = wx.getStorageSync('openid');

if(openid) {
param['openid'] = openid;
}
}

const pages = getCurrentPages();
const page = pages[pages.length - 1];

param['page_route'] = page.route; // 当前页面路由
param['page_options'] = JSON.stringify(page.options); // 当前页面入参
param['data_key'] = key;
param['data_content'] = data ? JSON.stringify(data) : null;

// 上报
wx.request({
url: 'https://report.log.hongfs.cn',
method: 'POST',
header: {
'Content-Type': 'application/x-www-form-urlencoded',
},
data: param,
});
};

export default log;

使用:(官方模板)

pages\index\index.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
// index.js
// 获取应用实例
const app = getApp()

import $log from '../../utils/log';

Page({
data: {
motto: 'Hello World',
userInfo: {},
hasUserInfo: false,
canIUse: wx.canIUse('button.open-type.getUserInfo'),
canIUseGetUserProfile: false,
canIUseOpenData: wx.canIUse('open-data.type.userAvatarUrl') && wx.canIUse('open-data.type.userNickName') // 如需尝试获取用户信息可改为false
},
// 事件处理函数
bindViewTap() {
wx.navigateTo({
url: '../logs/logs'
})
},
onLoad() {
$log('onLoad');

if (wx.getUserProfile) {
$log('当前客户端支持 wx.getUserProfile');

this.setData({
canIUseGetUserProfile: true
})
} else {
$log('当前客户不端支持 wx.getUserProfile');
}
},
getUserProfile(e) {
// 推荐使用wx.getUserProfile获取用户信息,开发者每次通过该接口获取用户个人信息均需用户确认,开发者妥善保管用户快速填写的头像昵称,避免重复弹窗
wx.getUserProfile({
desc: '展示用户信息', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写
success: (res) => {
console.log(res)
$log('wx.getUserProfile:success', res);
this.setData({
userInfo: res.userInfo,
hasUserInfo: true
});
},
fail: (err) => {
$log('wx.getUserProfile:fail', err);
},
})
},
getUserInfo(e) {
// 不推荐使用getUserInfo获取用户信息,预计自2021年4月13日起,getUserInfo将不再弹出弹窗,并直接返回匿名的用户个人信息
console.log(e)
$log('getUserInfo', e);
this.setData({
userInfo: e.detail.userInfo,
hasUserInfo: true
});
}
})

往上