github.com/hy3/cuto@v0.9.8-0.20160830082821-aa6652f877b7/log/log.go (about)

     1  // Copyright 2015 unirita Inc.
     2  // Created 2015/04/15 honda
     3  
     4  package log
     5  
     6  import (
     7  	"fmt"
     8  	"os"
     9  	"path/filepath"
    10  
    11  	"github.com/cihub/seelog"
    12  
    13  	"github.com/unirita/cuto/util"
    14  )
    15  
    16  const lockHeader = "Unirita_CutoLog_"
    17  
    18  var lockTimeout = 1000
    19  var valid = false
    20  var locker *util.LockHandle
    21  
    22  // ロガーの初期化処理を行う
    23  //
    24  // param ; dir       ログファイルの出力先ディレクトリ。
    25  //
    26  // param : name      ログファイルの種別(例:master、servant)。
    27  //
    28  // param : identifer ロック用ファイルに(付与する識別ID(例:servantはListePort)。
    29  //
    30  // param : level     出力ログレベル(trace,debug,info,warn,error,criticalのいずれかを指定)
    31  //
    32  // param : maxSizeKB ログファイルの最大サイズ。この値を超えるとログローテーションが発生する。
    33  //
    34  // param : maxRolls  ログファイルの最大世代数
    35  //
    36  // param : timeoutSec  ロックのタイムアウト秒
    37  //
    38  // return : エラー情報を返す。
    39  func Init(dir string, name string, identifer string, level string, maxSizeKB int, maxRolls int, timeoutSec int) error {
    40  	var lockErr error
    41  	lockName := lockHeader + name
    42  	if identifer != "" {
    43  		lockName = lockName + "_" + identifer
    44  	}
    45  	lockName = lockName + ".lock"
    46  	locker, lockErr = util.InitLock(lockName)
    47  	if lockErr != nil {
    48  		return lockErr
    49  	}
    50  	if timeoutSec > 0 {
    51  		lockTimeout = timeoutSec * 1000
    52  	}
    53  
    54  	logfile := filepath.Join(dir, name) + ".log"
    55  	config := generateConfigString(logfile, level, maxSizeKB, maxRolls)
    56  	logger, err := seelog.LoggerFromConfigAsString(config)
    57  	if err != nil {
    58  		Term()
    59  		return err
    60  	}
    61  
    62  	if err := makeFileIfNotExist(logfile); err != nil {
    63  		Term()
    64  		return err
    65  	}
    66  
    67  	seelog.ReplaceLogger(logger)
    68  	valid = true
    69  
    70  	return nil
    71  }
    72  
    73  // ロガーの終了処理を行う。
    74  func Term() {
    75  	locker.TermLock()
    76  	valid = false
    77  }
    78  
    79  // traceレベルでログメッセージを出力する。
    80  //
    81  // param : msg 出力するメッセージ。複数指定した場合は結合して出力される。
    82  func Trace(msg ...interface{}) {
    83  	if !valid {
    84  		return
    85  	}
    86  	locker.Lock(lockTimeout)
    87  	defer locker.Unlock()
    88  	seelog.Trace(msg...)
    89  }
    90  
    91  // debugレベルでログメッセージを出力する。
    92  //
    93  // param : msg 出力するメッセージ。複数指定した場合は結合して出力される。
    94  func Debug(msg ...interface{}) {
    95  	if !valid {
    96  		return
    97  	}
    98  	locker.Lock(lockTimeout)
    99  	defer locker.Unlock()
   100  	seelog.Debug(msg...)
   101  }
   102  
   103  // infoレベルでログメッセージを出力する。
   104  //
   105  // param : msg 出力するメッセージ。複数指定した場合は結合して出力される。
   106  func Info(msg ...interface{}) {
   107  	if !valid {
   108  		return
   109  	}
   110  	locker.Lock(lockTimeout)
   111  	defer locker.Unlock()
   112  	seelog.Info(msg...)
   113  }
   114  
   115  // warnレベルでログメッセージを出力する。
   116  //
   117  // param : msg 出力するメッセージ。複数指定した場合は結合して出力される。
   118  func Warn(msg ...interface{}) {
   119  	if !valid {
   120  		return
   121  	}
   122  	locker.Lock(lockTimeout)
   123  	defer locker.Unlock()
   124  	seelog.Warn(msg...)
   125  }
   126  
   127  // errorレベルでログメッセージを出力する。
   128  //
   129  // param : msg 出力するメッセージ。複数指定した場合は結合して出力される。
   130  func Error(msg ...interface{}) {
   131  	if !valid {
   132  		return
   133  	}
   134  	locker.Lock(lockTimeout)
   135  	defer locker.Unlock()
   136  	seelog.Error(msg...)
   137  }
   138  
   139  // criticalレベルでログメッセージを出力する。
   140  // この関数が呼び出されると、ただちにログのフラッシュが行われる。
   141  //
   142  // param : msg 出力するメッセージ。複数指定した場合は結合して出力される。
   143  func Critical(msg ...interface{}) {
   144  	if !valid {
   145  		return
   146  	}
   147  	locker.Lock(lockTimeout)
   148  	defer locker.Unlock()
   149  	seelog.Critical(msg...)
   150  }
   151  
   152  func makeFileIfNotExist(logfile string) error {
   153  	locker.Lock(lockTimeout)
   154  	defer locker.Unlock()
   155  	if _, err := os.Stat(logfile); !os.IsNotExist(err) {
   156  		// ファイルが存在する場合は何もしない。
   157  		// os.IsExistはerr=nilのときfalseを返すため、os.IsNotExistで判定している。
   158  		return nil
   159  	}
   160  
   161  	file, err := os.Create(logfile)
   162  	if err != nil {
   163  		return err
   164  	}
   165  
   166  	file.Close()
   167  	return nil
   168  }
   169  
   170  func generateConfigString(logfile string, level string, maxSizeKB int, maxRolls int) string {
   171  	format := `
   172  <seelog type="sync" minlevel="%s">
   173      <outputs formatid="common">
   174          <rollingfile type="size" filename="%s" maxsize="%d" maxrolls="%d" />
   175      </outputs>
   176      <formats>
   177          <format id="common" format="%%Date(2006-01-02 15:04:05.000) [%d] [%%LEV] %%Msg%%n"/>
   178      </formats>
   179  </seelog>`
   180  
   181  	// rollingfileのmaxrollsの数字は、書き込み中のログファイルを含まずにカウントするため引数をデクリメントする。
   182  	maxRolls--
   183  	return fmt.Sprintf(format, level, logfile, maxSizeKB*1024, maxRolls, os.Getpid())
   184  }