Как дополнительно настроить транспорты Winston при входе в Stackdriver из GKE - PullRequest
2 голосов
/ 29 октября 2019

У меня есть приложение Node.js, которое работает в контейнере Docker в Google Kubernetes Engine. Я установил класс ведения журнала, который использует Winston (v3.2.1) с двумя определенными транспортами;один для входа в консоль и один для входа в Stackdriver (с использованием @google-cloud/logging-winston (v3.0.0)).

С обоими определенными транспортными системами все хорошо, и я вижу журналы в Stackdriver. Журналы консоли идут на projects/[project-id]/logs/stdout, а журналы Stackdriver - на projects/[project-id]/logs/winston_log.

Однако я хочу настроить регистратор так, чтобы при локальной отладке журналы отправлялись только на консоль и при работе в GKE. , журналы отправляются только в Stackdriver следующим образом:

  // Configure console logger
  private readonly consoleLogger = new winston.transports.Console({
    format: combine(
      colorize(),
      simple(),
      printf(context => {
        return `[${context.level}]${context.message}`;
      }),
    ),
  });

  // Configure Stackdriver logger
  private readonly stackdriverLogger = new LoggingWinston({
    serviceContext: {
      service: this.serviceName,
    },
  });

  // Create Winston logger
  private readonly logger = winston.createLogger({
    level: process.env.LOG_LEVEL || 'info',
    format: json(),
    defaultMeta: {
      service: this.serviceName,
    },
    // This line does not work:
    transports: [process.env.NODE_ENV === 'development' ? this.consoleLogger : this.stackdriverLogger],
  });

Цель в том, что если NODE_ENV равен development, используйте консольный регистратор, в противном случае используйте регистратор Stackdriver. Однако, когда я внедряю это в GKE, я вижу следующие ошибки в журнале консоли Stackdriver (и ничего в projects/[project-id]/logs/winston_log):

[winston] Attempt to write logs with no transports { // Logged message }

Когда я запускаю этот код локально на моем компьютере разработчика с NODE_ENV=development, Я вижу журналы в своей локальной консоли и, если я установил NODE_ENV=production, я вижу журналы в Stackdriver.

Если я удаляю троичный оператор, и оба транспорта определены и развернуты в GKE, я не вижуВышеупомянутая ошибка и ведение журнала работают правильно для обоих транспортов:

transports: [this.consoleLogger, this.stackdriverLogger],

Может ли кто-нибудь помочь мне правильно настроить это?

РЕДАКТИРОВАТЬ

Добавлен полный файл Logger.ts дляконтекст:

import { LoggerService } from '@nestjs/common';
import * as winston from 'winston';
const { colorize, combine, json, printf, simple } = winston.format;
import { LoggingWinston } from '@google-cloud/logging-winston';
import cls from 'cls-hooked';
import { ConfigManager } from '../config';
import { TraceId } from '../middleware/traceId/constants';

export class Logger implements LoggerService {
  private readonly serviceName: string = process.env.SERVICE_NAME;

  private readonly consoleLogger = new winston.transports.Console({
    format: combine(
      colorise(),
      simple(),
      printf(context => {
        return `[${context.level}]${context.message}`;
      }),
    ),
  });

  private stackdriverLogger = new LoggingWinston({
    serviceContext: {
      service: this.serviceName,
    },
  });

  private readonly logger = winston.createLogger({
    level: process.env.LOG_LEVEL || 'info',
    format: json(),
    defaultMeta: {
      service: this.serviceName,
    },
    transports: [process.env.NODE_ENV === 'development' ? this.consoleLogger : this.stackdriverLogger]
  });

  constructor(private readonly context?: string) {}

  public verbose(message: string, context?: string) {
    const log = this.buildLog(message, context);
    this.logger.verbose(log.message, log.metadata);
  }

  public debug(message: string, context?: string) {
    const log = this.buildLog(message, context);
    this.logger.debug(log.message, log.metadata);
  }

  public log(message: string, context?: string) {
    const log = this.buildLog(message, context);
    this.logger.info(log.message, log.metadata);
  }

  public warn(message: string, context?: string) {
    const log = this.buildLog(message, context);
    this.logger.warn(log.message, log.metadata);
  }

  public error(message: string, trace?: string, context?: string) {
    const log = this.buildLog(message, context, trace);
    this.logger.error(log.message, log.metadata);
  }

  private buildLog(message: string, context?: string, trace?: string) {
    const ctx = context || this.context;
    const traceId = this.getTraceId();

    return {
      message: `[${ctx}] ${message}`,
      metadata: {
        traceId,
        source: ctx,
        stackTrace: trace,
      },
    };
  }

  private getTraceId(): string {
    const clsNamespace = cls.getNamespace(TraceId.Namespace);
    if (!clsNamespace) {
      return null;
    }
    return clsNamespace.get(TraceId.Key);
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...