「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」に上記と同様なログが保存されます。