My-MC
@My-MC

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

ログがファイルに出力されない

解決したいこと

Denoを使ってWebAPIを作っています。
Loggerの実装中に、consoleにはログが出力されるがfileには出力されないという問題に遭遇しました。
解決法を教えてください。

発生している問題・エラー

❯ deno run --allow-net --allow-read --allow-write .\main.ts 
2022-07-08T19:48:21+09:00 INFO    Starting server

該当するソースコード

APIサーバー本体

main.ts
import { config, serve } from "./deps.ts";
import { Logger } from "./logger.ts";

const env = config();
const PORT = Number(env.PORT);

await Logger.info("Starting server");

function handler(_req: Request): Response {
  Logger.debug("Get response")
  return new Response("Hello, World!");
}

await serve(handler, { port: PORT });

ロガー

logger.ts

import { config } from "./deps.ts";
import * as log from "https://deno.land/std@0.146.0/log/mod.ts";
import { LogRecord } from "https://deno.land/std@0.146.0/log/mod.ts";

const env = config();
const logfile = String(env.LOG_FILE);

const formatter = (logRecord: LogRecord) => {
  const { datetime, levelName, msg } = logRecord;

  const d = new Date(datetime.getTime() - datetime.getTimezoneOffset() * 6e4);
  const logTime = d.toISOString().slice(0, -5) +
    d.toString().replace(/^.*GMT([-+]\d{2})(\d{2}).*$/, "$1:$2");

  return `${logTime} ${levelName.padEnd(7)} ${msg}`;
};

await log.setup({
  handlers: {
    console: new log.handlers.ConsoleHandler("DEBUG", {
      formatter: formatter,
    }),

    file: new log.handlers.FileHandler("DEBUG", {
      filename: logfile,
      // you can change format of output message using any keys in `LogRecord`.
      formatter: formatter,
    }),
  },

  loggers: {
    // configure default logger available via short-hand methods above.
    default: {
      level: "DEBUG",
      handlers: ["console", "file"],
    },

    tasks: {
      level: "ERROR",
      handlers: ["console"],
    },
  },
});

const Logger = log.getLogger();

export { Logger };

deps

deps.ts
import ky from "https://cdn.skypack.dev/ky?dts";
import { serve } from "https://deno.land/std@0.119.0/http/server.ts";
import { config } from "https://deno.land/x/dotenv@v3.2.0/mod.ts";
import { deserializeFeed } from "https://deno.land/x/rss@0.5.6/mod.ts";

export { config, deserializeFeed, ky, serve };

denoのバージョン

deno 1.23.2 (release, x86_64-pc-windows-msvc)
v8 10.4.132.8
typescript 4.7.2

自分で試したこと

ログをデバッグ単位に設定したり、logをawaitにしても出力されませんでした。

0

1Answer

FileHandler はログを一時的にバッファリングして、ある程度まとめてからファイルに書き出すのですが、どうやら serve() でサーバが起動するとうまく書き出してくれなくなるようです。以下のように強制的に書き出してみてください。

main.ts
function flushLog() {
  Logger.handlers.forEach((handler) => {
    if (handler instanceof log.handlers.FileHandler) {
      handler.flush();
    }
  });
}

...

await Logger.info("Starting server");
flushLog();

...

// サーバを Ctrl-C で止めたときにも flushLog() を呼ぶ
Deno.addSignalListener("SIGINT", () => {
  flushLog();
  Deno.exit();
});

await serve(handler, { port: PORT });
1Like

Comments

  1. @My-MC

    Questioner

    ご回答ありがとうございます。
    仕組みを込めての丁寧なありがとうございました。

Your answer might help someone💌