在开发微信小程序时,为了更好地调试和维护代码,通常需要记录日志信息。我尝试了多种日志库,包括Winston、pion和loglevel,并最终选择了loglevel作为日志库,并实现了日志上传到服务器的功能。本文详细记录了这一过程,以供参考。
最初,我尝试在微信小程序中使用Winston日志库。然而,Winston依赖Node.js的部分核心模块(如stream、path和os),这些模块在微信小程序的环境中不可用。这导致了编译和运行时错误。
示例错误信息:
Module not found: Error: Can't resolve 'stream' in 'node_modules/winston/dist/winston/transports'
为了绕过上述这些问题,我尝试手动编写一个简单的日志库。该库能够记录日志,并根据配置将日志发送到服务器
示例代码:
// utils/logger.js
import {
getEnvironment
} from './env'
class Logger {
constructor(config) {
this.level = config.level || 'info';
this.sendToServer = config.sendToServer || false;
this.serverUrl = config.serverUrl || '';
this.printInDev = config.printInDev || false;
}
log(level = this.level, message) {
const env = getEnvironment()
if (this.shouldLog(level)) {
if (typeof message === 'undefined') {
message = level;
level = this.level;
}
//通过配置参数控制是否打印
if (this.printInDev || env == 'prod' || env == 'test') {
console.log(`[${level.toUpperCase()}]: ${message}`);
}
if (this.sendToServer) {
if (env == 'prod' || env == 'test') {
this.sendLogToServer(level, message);
}
}
}
}
info(message) {
this.log('info', message);
}
warn(message) {
this.log('warn', message);
}
error(message) {
this.log('error', message);
}
shouldLog(level) {
const levels = ['info', 'warn', 'error'];
const currentLevelIndex = levels.indexOf(this.level);
const messageLevelIndex = levels.indexOf(level);
return messageLevelIndex >= currentLevelIndex;
}
sendLogToServer(level, message) {
wx.request({
url: this.serverUrl,
method: 'POST',
data: {
level,
message,
},
success(res) {
console.log('Log sent to server:', res);
},
fail(err) {
console.error('Failed to send log to server:', err);
},
});
}
}
module.exports = Logger;
app.js使用:
引入模块
const Logger = require('./utils/logger.js');
在小程序onLaunch中初始化并挂在到wx
//实例话 Logger
const logger = new Logger({
level: env, // 可配置为 'info', 'warning', 'error'
sendToServer: true, // 是否发送到服务端
printInDev: false, //开发环境是否打印日志
serverUrl: 'https://your-server-url.com/logs', // 服务端 URL
});
wx.logger = logger; //挂载到wx
使用小程序onError捕获异常
onError(error) {
wx.logger.log(error);
},
最后重写小程序page(),使日志库能够监听页面生命周期
// utils/overridePage.js
function overridePage() {
const logger = wx.logger;
const originalPage = Page;
Page = function (pageConfig) {
const originalOnLoad = pageConfig.onLoad;
pageConfig.onLoad = function (options) {
logger.log(`Page loaded: ${this.route}`);
if (originalOnLoad) originalOnLoad.call(this, options);
};
const originalOnShow = pageConfig.onShow;
pageConfig.onShow = function () {
logger.log(`Page shown: ${this.route}`);
if (originalOnShow) originalOnShow.call(this);
};
const originalOnHide = pageConfig.onHide;
pageConfig.onHide = function () {
logger.log(`Page hidden: ${this.route}`);
if (originalOnHide) originalOnHide.call(this);
};
const originalOnUnload = pageConfig.onUnload;
pageConfig.onUnload = function () {
logger.log(`Page unloaded: ${this.route}`);
if (originalOnUnload) originalOnUnload.call(this);
};
originalPage(pageConfig);
};
}
module.exports = overridePage;
const overridePage = require('./utils/overridePage.js');
wx.logger = logger; //挂载到wx
overridePage(); //重写page
为了简化日志记录,我们决定使用更轻量级的loglevel库。loglevel可以很方便地在微信小程序中使用,并且我们可以通过插件实现日志上传功能。
安装loglevel:
npm install loglevel
下载完成后,需要使用微信的npm构建功能
在小程序内使用loglevel
app.js
import log from 'loglevel';
onlaunch(){
log.setLevel('info'); //设置 loglevel 日志输出级别
log.trace('This is a trace message');
log.debug('This is a debug message');
log.info('This is an info message');
log.warn('This is a warning message');
log.error('This is an error message');
}
日志上传服务器,loglevel的上传插件使用XMLHttpRequest()上传,小程序内不支持,需要重写上传模块,下附上传插件源码链接
https://github.com/artemyarulin/loglevel-serverSend/blob/master/loglevel-serverSend.js
重写上传模块
// utils/loglevel-server-send-wx.js
var loglevelServerSend = function (options) {
var _url = options && options.url || 'http://localhost:8000/main/log',
_callOriginal = options && options.callOriginal || false,
_prefix = options && options.prefix,
_sendQueue = [],
_isSending = false;
var _sendNextMessage = function () {
if (!_sendQueue.length || _isSending) return;
_isSending = true;
var msg = _sendQueue.shift();
wx.request({
url: _url,
method: 'POST',
data: msg,
header: {
'Content-Type': 'text/plain'
},
success: function () {
_isSending = false;
setTimeout(_sendNextMessage, 0);
},
fail: function () {
_isSending = false;
setTimeout(_sendNextMessage, 0);
}
});
};
wx.log = {
log: function (level, message) {
if (typeof _prefix === 'string') message = _prefix + message;
else if (typeof _prefix === 'function') message = _prefix(level, message);
else message = level + ': ' + message;
console.log(`[${level.toUpperCase()}]: ${message}`);
if (options && options.sendToServer) {
_sendQueue.push(message);
_sendNextMessage();
}
},
info: function (message) {
this.log('info', message);
},
warn: function (message) {
this.log('warn', message);
},
error: function (message) {
this.log('error', message);
}
};
};
module.exports = loglevelServerSend;
在app.js 中调用
const loglevelServerSend = require('./utils/loglevel-server-send-wx.js');
onLaunch(){
log.setLevel('info'); //设置 日志输出级别
wx.log = log; //挂载到wx
//wx.log*等触发日志上传服务端
loglevelServerSend({
url: 'https://your-server-url.com/logs',
prefix: function (level, message) {
return `[${new Date().toISOString()}] [${level.toUpperCase()}]: ${message}`;
},
sendToServer: env === 'dev' || env === 'test' || env === 'pre' || env === 'prod', //设置允许上传日志的环境
callOriginal: false // 上传日志时是否控制台打印
});
wx.log.level = 'info'; //动态改变日志输出的级别
}
//捕获异常
onError(error) {
wx.log.log('error', error);
},
如需根据小程序环境动态设置日志输出级别,添加以下模块
// utils/environment.js
function getEnvironment() {
return __wxConfig.envVersion;
}
function getLogLevel(env) {
const levels = {
'develop': 'info',
'trial': 'warning',
'pre': 'error',
'release': 'error'
};
return levels[env] || 'info';
}
module.exports = { getEnvironment, getLogLevel };
通过上述步骤,我成功在微信小程序中集成了loglevel日志库,并实现了日志上传到服务器的功能。这不仅提高了日志管理的灵活性,也为未来的维护和调试提供了更强大的支持。
loglevel
微信小程序开发文档
希望这篇文章能对在微信小程序中集成日志库的开发者有所帮助。如果有任何问题,欢迎留言讨论。