2

我在 App Engine Standard 和 Flexible 上使用 Node.js。

在日志查看器中,是否可以显示嵌套在请求日志中的应用程序日志?

4

2 回答 2

3

是的,可以关联应用程序日志和请求日志。这是日志查看器中的最终结果:

在此处输入图像描述

为此,您可以:

在您的应用程序中同时使用@google-cloud/trace-agent@google-cloud/logging-bunyan模块。当您这样做时,您的日志会自动使用正确的跟踪 ID 进行注释(请参阅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');
于 2018-06-16T07:09:34.150 回答
2

我也曾在某个时候遇到过同样的问题,并做了一些解决方法来解决这个问题。但是在上述解决方案中,在您没有 req, res 对象引用的某些用例中可能无济于事。

所以这里的解决方案。它会将所有日志分组在请求日志下。

在此处输入图像描述

还创建了 -> NPM 模块

文件名:相关日志.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 };

希望这可以帮助某人。

于 2019-02-07T08:10:15.727 回答