masalibの日記

システム開発、運用と猫の写真ブログです

golang の入門 Fiber4(ロガー設定)

実際に運用をしていると絶対に必要なのがアクセスログです。 APPサーバーとして運用する場合はそこまで細かいのはいらないのですが、 apacheのログみたいなものを出力したいと思います

apacheのログのフォーマットは以下のような形です。標準じゃないです

 LogFormat "%a %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined

Fiberでログをファイルに出力するために、logger.ConfigOutput フィールドを使用してファイルを指定することができます。 以下にログを特定のフォルダに保存する方法を示します。

まず、Goの標準ライブラリを使用してログファイルを作成し、 そのファイルをlogger.ConfigOutputフィールドに設定します。

実例のプログラム

以下は、ログをlogsフォルダ内のaccess.logファイルに保存する例です。

package main

import (
    "github.com/gofiber/fiber/v2"
    "github.com/gofiber/fiber/v2/middleware/logger"
    "os"
    "path/filepath"
    "time"
)

func main() {
    // Create logs directory if it doesn't exist
    logDir := "logs"
    if _, err := os.Stat(logDir); os.IsNotExist(err) {
        os.Mkdir(logDir, os.ModePerm)
    }

    // Open log file
    logFile, err := os.OpenFile(filepath.Join(logDir, "access.log"), os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
    if err != nil {
        panic(err)
    }
    defer logFile.Close()

    app := fiber.New()

    // Define a custom log format
    logFormat := "${ip} - - [${time}] \"${method} ${path} ${protocol}\" ${status} ${bytesSent} \"${referer}\" \"${ua}\"\n"

    app.Use(logger.New(logger.Config{
        Format: logFormat,
        TimeFormat: "02/Jan/2006:15:04:05 -0700",
        TimeZone: "Local",
        Output: logFile,
    }))

    app.Get("/", func(c *fiber.Ctx) error {
        return c.SendString("Hello, World!")
    })

    app.Listen(":3000")
}

説明

  1. ログフォルダの作成: go logDir := "logs" if _, err := os.Stat(logDir); os.IsNotExist(err) { os.Mkdir(logDir, os.ModePerm) } logsというフォルダが存在しない場合、新しく作成します。

  2. ログファイルのオープン: go logFile, err := os.OpenFile(filepath.Join(logDir, "access.log"), os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) if err != nil { panic(err) } defer logFile.Close() logs/access.logというファイルを読み書きモードでオープンし、存在しない場合は新しく作成します。ファイルはアプリケーション終了時に閉じられます。

  3. Logger ミドルウェアの設定: go app.Use(logger.New(logger.Config{ Format: logFormat, TimeFormat: "02/Jan/2006:15:04:05 -0700", TimeZone: "Local", Output: logFile, })) ログフォーマットとファイル出力設定を指定します。

TimeFormatの補足

TimeFormat フィールドは、ログエントリ内のタイムスタンプのフォーマットを指定するために使用されます。このフォーマットは、Goの標準ライブラリ time パッケージで提供されるフォーマット文字列に従います。

Goの時間フォーマットは他の言語と異なり、特定のサンプル時間 Mon Jan 2 15:04:05 -0700 MST 2006 に基づいています。このサンプル時間の各部分は、異なる時間コンポーネントを表します。具体的には:

  • 02 = 日 (02)
  • Jan = 月 (1月)
  • 2006 = 年 (2006年)
  • 15 = 時 (15時、24時間形式)
  • 04 = 分 (04分)
  • 05 = 秒 (05秒)
  • -0700 = タイムゾーンのオフセット (-07:00)

ApacheLogFormatに対応するようにするため、以下のようなフォーマットを指定します:

TimeFormat: "02/Jan/2006:15:04:05 -0700"

フォーマットの詳細 - 02 日 (先頭にゼロをつける) - / スラッシュ (文字通りのスラッシュ) - Jan 月 (短縮形式) - / スラッシュ - 2006 年 (4桁) - : コロン - 15 時 (24時間形式) - : コロン - 04 分 - : コロン - 05 秒 - スペース - -0700 タイムゾーンオフセット (UTCからのオフセット)

このフォーマットは、以下のようなタイムスタンプを生成します:

23/Jun/2024:15:04:05 -0700

出力サンプル

127.0.0.1 - - [23/Jun/2024:20:32:45 +0900] "GET / http" 200 13 "" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36"
127.0.0.1 - - [23/Jun/2024:20:32:45 +0900] "GET / http" 200 13 "" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36"
127.0.0.1 - - [23/Jun/2024:20:32:46 +0900] "GET / http" 200 13 "" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36"
127.0.0.1 - - [23/Jun/2024:20:33:04 +0900] "GET / http" 200 13 "" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36"
127.0.0.1 - - [23/Jun/2024:20:33:05 +0900] "GET / http" 200 13 "" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36"
127.0.0.1 - - [23/Jun/2024:20:33:05 +0900] "GET / http" 200 13 "" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36"