「Raspbian「stretch」上にGO言語をインストール」でGo言語をインストールしましたが、今回は定周期タイマーを持つアプリをGo言語で作成し、動作状態をログとして保存します。アプリはWindows10上のVisual Studio Codeで開発し、Raspberry Pi上で動作させます。
開発環境
- Raspbian:buster
- go言語のバージョン:go1.13.4
- コーディング環境:Visual Studio Code 1.44.2
Go言語パッケージのインストール
次のコマンドでログ用のパッケージ「rotatelogs」「logf」をインストールします。
$ go get github.com/lestrrat-go/file-rotatelogs $ go get github.com/spiegel-im-spiegel/logf
パッケージ「rotatelogs」
ログファイルの分割とローテーション機能を持つパッケージで、ログを作成するときに次のようにパラメータを与えることができます。3行目でログ出力ファイル先、4行目でログファイルの切り替えタイミング、この場合1時間ごとを示します。詳細については「lestrrat-go/file-rotatelogs」に示します。
// Rotate every hour rotatelogs.New( "/var/log/myapp/log.%Y%m%d", rotatelogs.WithRotationTime(time.Hour), )
パッケージ「logf 」
ログメッセージ毎に 次のような出力レベルの設定を行い,あらかじめ指定したレベル以下のメッセージについては、フィルタリングできるパッケージで、詳細については「spiegel-im-spiegel/logf」に示します。
- logf.SetMinLevel() ← ログレベルの設定
- logf.Tracef()
- logf.Debugf()
- logf.Printf()
- logf.Warnf()
- logf.Errorf()
- logf.Fatalf()
アプリの作成
作業フォルダ「gotimer」に次に示す「timermain.go」「timerlib.go」「loglib.go」を作成します。
- package名は「main」固定とします。これにより、別ファイルの変数も参照可能となります。最初の文字が大文字で始まる変数、関数等は、外部パッケージ(package名が異なる)から参照可能になります。
- package名「main」の関数名「main」がメインルーチンとなります。メインルーチンの前には初期化ルーチン「init」が最初に一度だけ実行されます。
- アプリは、メインルーチンからゴルーチン「ticker」を起動し、ゴルーチン「ticker」からチャンネル「timerch」を使用して現在時刻をメインルーチンに通知します。
メインルーチン「main」と初期化ルーチン「init」を次に示します。
- 10行目でログ機能を初期化します。4行目のように、importにログパッケージ「logf」を記述すれば、ログを取ることができます。
- 7行目でチャンネル「timerch」を作成し、15行目でゴルーチン「ticker」を起動し、19行目でゴルーチン「ticker」からチャンネル「timerch」を受け取り、その内容をロギングします。
timermain.go
package main import ( "github.com/spiegel-im-spiegel/logf" ) var timerch = make(chan string) func init() { loglib() logf.Print("************** Start Vital App *******") // this will not print } func main() { go ticker() for { select { case time := <-timerch: logf.Printf(time) } } logf.Printf("Exit") }
1秒周期の tickerを作成する「ticker」を次に示します。
- 10行目で1秒周期の tickerを作成します。
- 11行目のdeferキーワードで作成したtickerを関数終了時に実行します。
- 13行目でループ状態にして、15行目で1秒のイベントを検出すると、17行目でチャンネル「timerch」を発生します。
timerlib.go
package main import ( "time" "github.com/spiegel-im-spiegel/logf" ) func ticker() { t := time.NewTicker(1 * time.Second) //1秒周期の ticker defer t.Stop() for { select { case now := <-t.C: logf.Printf(now.Format(time.RFC3339)) timerch <- now.Format(time.RFC3339) } } }
ログ機能を設定する「loglib」を次に示します。
- 20行目で、golangでlogを標準出力とテキストファイルの2箇所の出力するために、io.MultiWriterを使用します。
loglib.go
package main import ( "io" "os" rotatelogs "github.com/lestrrat-go/file-rotatelogs" "github.com/spiegel-im-spiegel/logf" ) var logpoint = 0 func loglib() { logf.SetMinLevel(logf.DEBUG) rl, err := rotatelogs.New("log/log.%Y%m%d%H%M.txt") if err != nil { logf.Fatal(err) return } ws := io.MultiWriter( rl, os.Stdout, ) logf.SetOutput(ws) }
アプリの実行
次のコマンドで作成したアプリをコンパイルして実行します。1秒ごとにtickerタイマーが起動し、チャンネル「timerch」を使用して現在時刻が送られていることが確認できます。
$ go build $ ./gotimer 2020/05/07 17:18:21 [INFO] ************** Start Vital App ******* 2020/05/07 17:18:22 [INFO] 2020-05-07T17:18:22+09:00 2020/05/07 17:18:22 [INFO] 2020-05-07T17:18:22+09:00 2020/05/07 17:18:23 [INFO] 2020-05-07T17:18:23+09:00 2020/05/07 17:18:23 [INFO] 2020-05-07T17:18:23+09:00 2020/05/07 17:18:24 [INFO] 2020-05-07T17:18:24+09:00 2020/05/07 17:18:24 [INFO] 2020-05-07T17:18:24+09:00 2020/05/07 17:18:25 [INFO] 2020-05-07T17:18:25+09:00 2020/05/07 17:18:25 [INFO] 2020-05-07T17:18:25+09:00 2020/05/07 17:18:26 [INFO] 2020-05-07T17:18:26+09:00 2020/05/07 17:18:26 [INFO] 2020-05-07T17:18:26+09:00
フォルダ「log」のファイル「log.202005070000.txt」に上記と同様なログが保存されます。