Функции Firebase: регистрация с помощью winston в консоли стека

Я не могу сделать Winston Logger для записи журналов в консоль стека. Я разворачиваю свои функции как функции Google Firebase (используя firebase deploy). console регистрация работает нормально, но мы не используем такой инструмент в проекте.

Что я пробовал:

Пожалуйста, предложите... Я устал от экспериментов (каждое повторное развертывание занимает время)

3 ответа

Решение

Наконец то, что я сделал - реализовал пользовательский транспорт, который на самом деле вызывает console.log под капотом. Это помогло.

const winston = require('winston');
const util = require('util');
const ClassicConsoleLoggerTransport = winston.transports.CustomLogger = function (options) {
    options = options || {};
    this.name = 'ClassicConsoleLoggerTransport';
    this.level = options.level || 'info';
    // Configure your storage backing as you see fit
};
util.inherits(ClassicConsoleLoggerTransport, winston.Transport);

ClassicConsoleLoggerTransport.prototype.log = function (level, msg, meta, callback) {
    let args = [msg, '---', meta];
    switch (level) {
        case 'verbose':
        case 'debug':
            console.log.apply(null, args);
            break;
        case 'notice':
        case 'info':
            console.info.apply(null, args);
            break;
        case 'warn':
        case 'warning':
            console.warn.apply(null, args);
            break;
        case 'error':
        case 'crit':
        case 'alert':
        case 'emerg':
            console.error.apply(null, args);
            break;
        default:
            console.log.apply(null, args);
    }
    callback(null, true);
};

Консольный транспорт Winston по умолчанию не работает, потому что он использует console._stdout.write когда это доступно, что не принимается Firebase Functions.

Теперь вы можете попробовать транспортный пакет Google Cloud для Stackdriver. Не использовал его и требует узла ^8.11.2 если вы используете Winston 3.

Документация по настройке Winston node.js здесь и здесь

Я добавил свою полную настройку ниже.

Важный момент:

      const format = winston.format.combine(winston.format.colorize({ all: true }))
const console = new winston.transports.Console({ format: winston.format.combine(format) })

const options = this.#explicitSetup ? { projectId: appConfig.firebase.options.projectId, keyFilename: `${rootDirname}/service-account-file.json` } : {}
const loggingWinston = new LoggingWinston(options)

const transports = emulators ? [console] : [console, loggingWinston]

this.#logger = winston.createLogger({
  level: this.#defaultLevel,
  transports
})

В принципе, если эмуляторы запущены, используйте средство ведения журнала консоли, иначе используйте средство ведения журнала консоли и транспорты драйвера стека. Вы можете проверить, запущены ли эмуляторы, выполнив проверку связи конечной точки функций (например, конечной точки / ping, которую вы создали) на localhost. Если он не существует, эмуляторы не работают или это производственная среда. Обратите внимание также на возможность использования явной настройки, при которой projectId и проходят внутрь.

Файл JSON для keyFilename можно создать здесь:

https://cloud.google.com/docs/authentication/getting-started

Мой полный logger.js код, если это помогает, следует:

      import winston from 'winston'
import { LoggingWinston } from '@google-cloud/logging-winston'
import { appConfig } from '../app-config.js'
import { rootDirname } from './root-dirname.js'
import { isObjectLike } from 'lodash-es'

// https://cloud.google.com/logging/docs/setup/nodejs

export class Logger {

  #logger
  #defaultLevel = 'debug'
  #explicitSetup = false

  constructor() {
    this.error = this.error.bind(this)
    this.warn = this.warn.bind(this)
    this.info = this.info.bind(this)
    this.debug = this.debug.bind(this)
    this.log = this.log.bind(this)
  }

  init(emulators) {

    // https://stackoverflow.com/a/64173978/1205871
    winston.addColors({
      error: 'red',
      warn: 'yellow',
      info: 'bold cyan',
      debug: 'bold green'
    })

    const format = winston.format.combine(winston.format.colorize({ all: true }))
    const console = new winston.transports.Console({ format: winston.format.combine(format) })

    const options = this.#explicitSetup ? { projectId: appConfig.firebase.options.projectId, keyFilename: `${rootDirname}/service-account-file.json` } : {}
    const loggingWinston = new LoggingWinston(options)

    const transports = emulators ? [console] : [console, loggingWinston]

    this.#logger = winston.createLogger({
      level: this.#defaultLevel,
      transports
    })
  }

  error(...args) {
    this.#logger.error(this.#argsToString(args))
  }

  warn(...args) {
    this.#logger.warn(this.#argsToString(args))
  }

  info(...args) {
    this.#logger.info(this.#argsToString(args))
  }

  debug(...args) {
    this.#logger.debug(this.#argsToString(args))
  }

  log(...args) {
    this.#logger[this.#defaultLevel](this.#argsToString(args))
  }

  #argsToString(args) {
    return args.map(arg => {
      const str = isObjectLike(arg) ? JSON.stringify(arg) : arg.toString()
      return str.trim()
    }).join(' \u2022\u2022 ')
  }
}

const blogger = new Logger()
export const logger = blogger
Другие вопросы по тегам