golangでLogファイルを作成する方法

2021-02-26

golangでLogファイルを作成する方法を記載します

何かとLog Fileを出す機会があると思います。 この記事を読めば、ログファイルを作成する際の勘所が伝わるかと思います。

ファイル構成

E:.
│  Config.ini
│  go.mod
│  go.sum
│  Trade.go
│─utils
|   logging.go
└─Config
    Config.go

mod 作成

go mod init config

modファイルとsumファイルを作成します。

Config.ini

ファイルの中身にはこのように記載します。

[LogSettings]
log_file = output.log

出力するファイル名をSettingファイルを

config.go

iniファイルを読み込み、構造体に詰め込む部分を記載します。

コード全体は下記の通り

package config

import (
    "log"
    "os"

    "gopkg.in/ini.v1"
)

type ConfigList struct {
    LogFile   string
}

var Config ConfigList

func init() {
    cfg, err := ini.Load("config.ini")
    if err != nil {
        log.Printf("Failed to read file: %v", err)
        os.Exit(1)
    }

    Config = ConfigList{
        LogFile:   cfg.Section("LogSettings").Key("log_file").String(),
    }
}

iniファイルをロードし、取り込み失敗時にはerrによりソフトが終了する部分。

    cfg, err := ini.Load("config.ini")
    if err != nil {
        log.Printf("Failed to read file: %v", err)
        os.Exit(1)
    }

定義した構造体の中身にiniファイルの中身を記載する箇所。 Sectionにはiniファイルで定義した []の中身に書いてあるセクション名を記載する。 Keyについてはセクションに含まれる要素に当たる、それぞれの名称を記載する。

    Config = ConfigList{
        LogFile:   cfg.Section("gotraing").Key("log_file").String(),
    }

logging.go

コード全体は下記のとおりです。

package utils

import (
    "io"
    "log"
    "os"
)

func LoggingSetting(logFile string) {
    logfile, err := os.OpenFile(logFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
    if err != nil {
        log.Fatalf("file=logFile err=%s", err.Error())
    }
    multiLogFile := io.MultiWriter(os.Stdout, logfile)
    log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
    log.SetOutput(multiLogFile)
}

Logファイルを作成する部分をこのように書きます。

    logfile, err := os.OpenFile(logFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)

OpenFileの引数が意味するところはこのとおりです。 第1引数は、ファイル名 第2引数は、フラグを指定する。 第3引数は、パーミッション

第2引数:フラグについて
  • os.O_RDONLY : Read Only
  • os.O_WRONLY : Write Only
  • os.O_RDWR : Read Write
  • os.O_APPEND : ファイルに追記
  • os.O_CREATE : 存在しない場合、新規作成

参考にした記事はコチラ Qiita記事:Goでファイル追記・存在しなかったらファイル作成したい!

第3引数:パーミッションに関する解説

0666については、作成するファイルのパーミッションを指定します。 4桁の数字が意味するところは、書く桁の数値に権限の対象が割り当てられています。 先頭の桁はまた別の意味があります。

※1 グループ その他 全て

※1 割り当てる数字で意味が変わる。(0,1,2,4)が指定可能

  • 特になし(0):何も指定しない
  • SUID(4):所有者の権限で動作する
  • SGID(2):所属のグループで動作する
  • スティッキービット(1):所有者以外は削除できない。但し書き込みは誰でも許可する。
モード アルファベット 権限
4 r 読み取り
2 w 書き込み
1 x 実行

6=4+2 ということで、読み書きを許可していることになります。

Logの中身の設定および、出力部分について記載。

    multiLogFile := io.MultiWriter(os.Stdout, logfile)
    log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
    log.SetOutput(multiLogFile)

ここではひとまず、日時とファイル名と挿入された行番号を出力します。

GO: Package log のConstantsにSetFlagで指定できる情報の詳細が記載されています。

Trade.go

先程作成した、configとutilsをパッケージとして読み込み 先程作成したLoggingSetting関数を呼び出しています。

package main

import (
    "config/config"
    "config/utils"
    "fmt"
)

func main() {
    utils.LoggingSetting(config.Config.LogFile)
    log.Println("Sample")
}

まとめ

Logファイルの出し方は奥深いものです。 情報として少なすぎても良くないですし、逆も然りで解析が困難になります。 少なすぎるよりは多すぎるほうがまだ救いはある気もしますが…

そんな優れたログを作成するような話はいつか記事にしたいものですが、 この記事も誰かの何かに参考になればと思います。