シングトン・ファイル



先日、私は過去に抱える問題の解決に出くわした.
JavaScriptをやっている人には誰かにとっては明らかなことだと思いますが、私にとっては夜明けまで時間がかかっていたので、誰か他の人を待ち続けていると思います.そして、それは良い笑いであなたの残りを提供します.
私はこのパターンが正式に呼ばれるものを知らないので、私はそれを「singletonファイル」と名付けました.

問題


私が持っていた問題は、ロギングのようなサービスで、ほとんどのモジュールが起動される前に利用できる必要があります.最初はほとんどのサービスと同様にinitLogging関数でこれを試してみました.しかし、システムが起動し、すべてのモジュールがインポートされているときに、モジュールのコードの一部がログ設定を実行する前に実行されていました.

解決策


解決は本当に狡猾ではありません、しかし、それは非常によく働きます(少なくとも私のために):あなたは実際のロガーのオブジェクトをモジュールからの輸出にします.

ログモジュールの定義


私は私の事のほとんどでウィンストンログシステムを使用しています.私はserilog/構造化されたログのものの外観が好きです、しかし、それは現在働くためにあまりに多くの手間がかかりませんでした.現在使用しているログモジュールは以下のコードのように見えます.警告-それは少し長いです.
import { createLogger, transports, format } from 'winston';

// Allow the logging level to be controlled at start time
let level = process.env.LOG_LEVEL;
if (process.env.NODE_ENV !== "test") {
  console.info(`Logging at ${level} level.`)
}

// This is the format for lines to be printed to console. The format varies
// depending on the environment.
const consoleLineFormat = format.printf(({ level, message, label, timestamp }) => {
  if (process.env.NODE_ENV === "production") {
    return `[${label}] ${level}: ${message}`;
  } else {
    return `${timestamp} [${label}] ${level}: ${message}`;
  }
});

let consoleFormat;
if (process.env.NODE_ENV === "production") {
  // Heroku captures info like timestamp anyway, don't duplicate it.
  consoleFormat = format.combine(
    format.splat(),
    consoleLineFormat
  );
} else {
  // Put more information in the dev logs
  consoleFormat = format.combine(
    format.splat(),
    format.colorize(),
    format.timestamp(),
    consoleLineFormat
  );
}

// For file logs, use JSON
const fileFormat = format.combine(
  format.splat(),
  format.json(),
  format.timestamp()
)

// Create the base logger; everything else comes from this.
// We always log to console; exceptions are always logged, regardless
// of the level that's set.
const base_logger = createLogger({
                              level: 'info',
                              transports: [
                                new transports.Console({ level: level, format: consoleFormat })
                              ],
                              exceptionHandlers: [
                                new transports.Console({ format: consoleFormat })
                              ]
                            });

// For development, also log to files. No point in that for Heroku.
if (process.env.NODE_ENV === "development") {
  base_logger
    .add(new transports.File({ filename: 'combined.log', level: 'debug', format: fileFormat }))
    .add(new transports.File({ filename: 'errors.log', level: 'error', format: fileFormat }));
}

// 'parentLogger' is exported to the other modules. They use the 'child'
// function to create a local logger, tagged with the module name.
export const parentLogger = Object();
type childOptions = {
  module: string;
}
parentLogger.child = function(opts: childOptions) {
  return base_logger.child({ label: opts.module });
}
それの長さの謝罪-私はビットを取るしようとしました、しかし、すべての理由のためにそこにあります、そして、私はそれが人々に役に立つかもしれないと思いました.

ログモジュールの使用


幸いにも、実際にそれを使用して簡単です.
import { parentLogger } from "./logger";
const logger = parentLogger.child({ module: "events" })
それです.今、ローカルコードは単にlogger.info、または任意のレベルを使用します.それはすべてのモジュールでloggerですので、私は他の名前を覚えている必要はありません.

なぜ作品


私が正直であるならば、私は詳細にこれを調査しませんでした.私は、ノードがモジュールが彼らが輸入しているモジュールが最初の走力を完了するまで、走らせないという理由でそれを想像します-さもなければ、それは依存関係を使用する悪夢です.誰かが確かに知っているか、異なるということを知っているならば、知らせてください.
それです.誰かを助ける希望!
ああ-そして、あなたが疑問に思っている場合は、イメージは完全に話に関係がないです.私は適切なポストイメージを見つけることができなかったので、代わりに“かわいい子犬”と行きました.