我想在日志语句中显示文件名
Posted
技术标签:
【中文标题】我想在日志语句中显示文件名【英文标题】:I want to display the file Name in the log statement 【发布时间】:2012-11-04 20:00:53 【问题描述】:对于任何级别的每个logger语句,我都需要显示执行日志语句的文件名,下面是我在下面给出的说明:
示例: 下面是从 JobWork.js
执行的行logger.info("getInCompleteJobs in job works");
实际:
2012-11-05T06:07:19.158Z - info: getInCompleteJobs in job works
必填:
2012-11-05T06:07:19.158Z - info JobWork.js : getInCompleteJobs in job works
如果不将文件名作为参数从日志语句中传递,它应该给出文件名。
【问题讨论】:
【参考方案1】:假设每个文件都是一个单独的节点进程,你可以使用类似process.argv[1].match(/[\w-]+\.js/gi)[0]
如果您正在寻找可以在模块中使用的东西,这可能会起作用:
process.mainModule.filename.match(/[\w-]+\.js/gi)[0]
【讨论】:
感谢您的评论,它仅用于每次提供相同的文件名,即开始执行的文件名 在这种情况下process.mainModule.filename.match(/[\w-]+\.js/gi)[0]
应该适合你! (它适用于每个根目录)您可以将其用作logger.info(process.mainModule.filename.match(/[\w-]+\.js/gi)[0] + "getInCompleteJobs in job works");
或看中并将其直接写入记录器。【参考方案2】:
您可以使用附加到 v8 的 Error
对象的堆栈跟踪信息来找出调用您的代码的文件/行。这种方法效果很好,但效果不佳;所以如果你在开发过程中使用它,你会希望在生产时禁用它。
所以你可以这样做:
var logger_info_old = logger.info;
logger.info = function(msg)
var fileAndLine = traceCaller(1);
return logger_info_old.call(this, fileAndLine + ":" + msg);
/**
* examines the call stack and returns a string indicating
* the file and line number of the n'th previous ancestor call.
* this works in chrome, and should work in nodejs as well.
*
* @param n : int (default: n=1) - the number of calls to trace up the
* stack from the current call. `n=0` gives you your current file/line.
* `n=1` gives the file/line that called you.
*/
function traceCaller(n)
if( isNaN(n) || n<0) n=1;
n+=1;
var s = (new Error()).stack
, a=s.indexOf('\n',5);
while(n--)
a=s.indexOf('\n',a+1);
if( a<0 ) a=s.lastIndexOf('\n',s.length); break;
b=s.indexOf('\n',a+1); if( b<0 ) b=s.length;
a=Math.max(s.lastIndexOf(' ',b), s.lastIndexOf('/',b));
b=s.lastIndexOf(':',b);
s=s.substring(a+1,b);
return s;
【讨论】:
感谢您的评论,请您看一下这个问题github.com/flatiron/winston/issues/197 好的,具体来说,你想让我对那个 github 问题做什么? mmalecki@github 是正确的:这是一个巨大的性能打击。这对于开发来说可能没问题,但对于生产来说就不行了。当然不能包含在温斯顿本身中。如果你想在你的程序中使用这个功能,你可以覆盖 log 函数(如我上面所示),或者你可以获取自己的 winston 副本,并制作一个具有必要修改的仅开发版本。 为什么b
是全球性的?【参考方案3】:
看起来您在这里使用的是 Winston - 我通常将 module
传递到我的记录器模块,然后将 Winston 的 label
属性设置为 module.filename
的解析版本。比如:
logger.js:
const path = require('path');
// Return the last folder name in the path and the calling
// module's filename.
const getLabel = function(callingModule)
const parts = callingModule.filename.split(path.sep);
return path.join(parts[parts.length - 2], parts.pop());
;
module.exports = function (callingModule)
return new winston.Logger(
transports: [new winston.transports.Console(
label: getLabel(callingModule)
)]
);
;
用法(假设模块为controllers/users.js
):
const logger = require('./logger')(module);
logger.info('foo');
结果:
2014-11-25T15:31:12.186Z - info: [controllers/users.js] foo
【讨论】:
干得好!注意:我无法让winston 将label
视为函数而不是字符串,因此我最终确定了return new winston.Logger...
之前的标签。反正效率更高。
谢谢,我从项目中提取的代码不正确。现已修复。
哇,使用“模块”作为参数太简单了。谢谢 :-)
这是我试过的所有其他方法中最酷的,但是你如何获得行号?
与@UalterJr 的评论相关。 - 您可以使用 Node 的 path.sep 进行可移植代码:const path = require('path'); ... var parts = callingModule.filename.split(path.sep)
【参考方案4】:
使用此代码,它将为您提供带有文件名和行号的日志。将此代码粘贴到新文件winston.js
中,这需要此文件才能使用。
var winston = require('winston')
var path = require('path')
var PROJECT_ROOT = path.join(__dirname, '..')
var appRoot = require('app-root-path');
const options =
file:
level: 'info',
filename: `$appRoot/logs/app.log`,
handleExceptions: true,
json: true,
maxsize: 5242880, // 5MB
maxFiles: 5,
colorize: false,
timestamp: true
,
console:
level: 'debug',
handleExceptions: true,
json: true,
colorize: true,
timestamp: true
;
var logger = new winston.Logger(
transports: [
new winston.transports.File(options.file),
new winston.transports.Console(options.console)
],
exitOnError: false // do not exit on handled exceptions
);
logger.stream =
write: function (message)
logger.info(message)
// A custom logger interface that wraps winston, making it easy to instrument
// code and still possible to replace winston in the future.
module.exports.debug = module.exports.log = function ()
logger.debug.apply(logger, formatLogArguments(arguments))
module.exports.info = function ()
logger.info.apply(logger, formatLogArguments(arguments))
module.exports.warn = function ()
logger.warn.apply(logger, formatLogArguments(arguments))
module.exports.error = function ()
logger.error.apply(logger, formatLogArguments(arguments))
module.exports.stream = logger.stream
/**
* Attempts to add file and line number info to the given log arguments.
*/
function formatLogArguments (args)
args = Array.prototype.slice.call(args)
var stackInfo = getStackInfo(1)
if (stackInfo)
// get file path relative to project root
var calleeStr = '(' + stackInfo.relativePath + ':' + stackInfo.line + ')'
if (typeof (args[0]) === 'string')
args[0] = calleeStr + ' ' + args[0]
else
args.unshift(calleeStr)
return args
/**
* Parses and returns info about the call stack at the given index.
*/
function getStackInfo (stackIndex)
// get call stack, and analyze it
// get all file, method, and line numbers
var stacklist = (new Error()).stack.split('\n').slice(3)
// stack trace format:
// http://code.google.com/p/v8/wiki/javascriptStackTraceApi
// do not remove the regex expresses to outside of this method (due to a BUG in node.js)
var stackReg = /at\s+(.*)\s+\((.*):(\d*):(\d*)\)/gi
var stackReg2 = /at\s+()(.*):(\d*):(\d*)/gi
var s = stacklist[stackIndex] || stacklist[0]
var sp = stackReg.exec(s) || stackReg2.exec(s)
if (sp && sp.length === 5)
return
method: sp[1],
relativePath: path.relative(PROJECT_ROOT, sp[2]),
line: sp[3],
pos: sp[4],
file: path.basename(sp[2]),
stack: stacklist.join('\n')
【讨论】:
else if (args[0].constructor === Object) args[0] = calleeStr + ' ' + JSON.stringify(args[0], null, 4);这个额外的 else 块也适用于记录对象。【参考方案5】:带有“consola”包的解决方案(仅限 ES 模块):
import createLogger from '@nitra/consola'
consola = createLogger(import.meta.url)
consola.debug('TEST')
输出:
[my-file.js] › TEST
【讨论】:
以上是关于我想在日志语句中显示文件名的主要内容,如果未能解决你的问题,请参考以下文章
写入信息不会显示在Start-Transcript转录的文件中
谁会用vba查询一个log文件,然后将结果显示在excel上