我在App Engine Standard和Flexible上使用Node.js.
在日志查看器中,是否可以显示嵌套在请求日志中的应用程序日志?
答案 0 :(得分:1)
是的,可以关联应用程序日志和请求日志。这是Logs Viewer中的最终结果:
要实现这一目标,您可以:
同时使用应用中的@google-cloud/trace-agent
和@google-cloud/logging-bunyan
模块。执行此操作时,将使用正确的跟踪ID自动注释日志(请参阅docs for Bunyan)。
从请求标题中提取跟踪ID
如果您不想使用Trace模块,可以从请求标头中提取跟踪ID,使用以下代码提取traceId
:
const traceHeader = req && req.headers ? req.headers['x-cloud-trace-context'] || '' : '';
const traceId = traceHeader ? traceHeader.split('/')[0] : '';
然后,您需要填充日志条目的trace
属性。使用Bunyan记录器时,请使用以下代码:
logger.info({
'logging.googleapis.com/trace': `projects/${project}/traces/${traceId}`
}, 'your message');
答案 1 :(得分:0)
我有时也遇到相同的问题,并做了一些工作来解决。但是在上述解决方案中,如果您不要求,则在某些情况下可能无济于事。
所以这里是解决方案。
文件名:correlate-logs.js
import bunyan from 'bunyan';
import { LOGGING_TRACE_KEY } from '@google-cloud/logging-bunyan';
import cls from 'cls-hooked';
import uuid from 'uuid/v1';
/**
* CreateLogger will return loggerContextMiddleware and log.
* Bind the loggerContextMiddleware on top to corelate other middleware logs. `app.use(loggerContextMiddleware);`
* then you can log like this anywhere `log.info('This is helpful to see corelated logs in nodejs.)` and it will show with-in reqeust log.
* @param {*} options
*/
export default function createLogger(projectId, bunyanLoggerOptions) {
if (!projectId || !bunyanLoggerOptions) throw new Error('Please pass the required fields projectId and bunyanLoggerOption');
const ns = cls.createNamespace(`logger/${uuid()}`); // To create unique namespace.
const logger = bunyan.createLogger(bunyanLoggerOptions);
/**
* Express Middleware to add request context to logger for corelating the logs in GCP.
* @param {*} req
* @param {*} res
* @param {*} next
*/
const loggerContextMiddleware = (req, res, next) => {
const traceHeader = (req && req.headers && req.headers['x-cloud-trace-context']) || '';
if (traceHeader) {
ns.bindEmitter(req);
ns.bindEmitter(res);
const traceId = traceHeader ? traceHeader.split('/')[0] : '';
const trace = `projects/${projectId}/traces/${traceId}`;
ns.run(() => {
ns.set('trace', trace);
next();
});
} else {
next();
}
};
/**
* Helper method to get the trace id from CLS hook.
*/
function getTrace() {
if (ns && ns.active) return ns.get('trace');
return '';
}
/**
* Simple wrapper to avoid pushing dev logs to cloud.
* @param {*} level
* @param {*} msg
*/
function printLog(level, ...msg) {
const trace = getTrace();
if (trace) { logger[level]({ [LOGGING_TRACE_KEY]: trace }, ...msg); } else { logger[level](...msg); }
}
/**
* Little wrapper to abstract the log level.
*/
const log = ['trace', 'debug', 'info', 'warn', 'error', 'fatal'].reduce((prev, curr) => ({ [curr]: (...msg) => printLog(curr, ...msg), ...prev }), {});
return { loggerContextMiddleware, log };
}
文件名:logger.js
import { LoggingBunyan } from '@google-cloud/logging-bunyan';
import createLogger from '../lib/corelate-logs';
import { getProjectId, ifDev } from './config';
// Creates a Bunyan Stackdriver Logging client
const loggingBunyan = new LoggingBunyan();
let loggerOption;
if (ifDev()) {
const bunyanDebugStream = require('bunyan-debug-stream'); // eslint-disable-line
loggerOption = {
name: 'my-service',
streams: [{
level: 'info',
type: 'raw',
stream: bunyanDebugStream({
forceColor: true,
}),
}],
serializers: bunyanDebugStream.serializers,
};
} else {
loggerOption = {
name: 'my-service',
level: 'info',
streams: [loggingBunyan.stream('info')],
};
}
const { loggerContextMiddleware, log } = createLogger(getProjectId() || 'dev', loggerOption);
export { loggerContextMiddleware, log };
希望这对某人有帮助。