Go でのログローテーションとファイル分割: logrus、zap、slog からのインサイト
James Reed
Infrastructure Engineer · Leapcell

はじめに
既存のログ記録ライブラリ、Go の組み込み log/slog
ログ記録ライブラリを含めて、通常はログファイルのローテーションと分割をサポートしています。ただし、これらの機能は直接組み込まれているわけではなく、有効にするには積極的に構成する必要があります。
この記事では、logrus、zap、公式の slog など、いくつかの一般的なログ記録ライブラリについて検討します。これらのライブラリの主要な設計要素を分析し、ログのローテーションと分割の構成をどのようにサポートするかについて説明します。
logrus、zap、slog の設計の簡単な分析
logrus、zap、slog の設計を比較すると、共通の重要なプロパティはすべて io.Writer
を含んでいることです。このプロパティは、ログ出力のターゲットの場所を決定するため、ログ記録フレームワークの設計において中心的な役割を果たします。
logrus ログ記録ライブラリ
locus は、構造化されたログ記録、ログレベル制御、およびその他の機能を提供する、Go 用の機能豊富なログ記録ライブラリです。
locus を使用すると、logrus.New()
を呼び出して Logger インスタンスを作成できます。このインスタンスを使用すると、ログ出力場所のカスタマイズやログの印刷など、多くの操作を実行できます。次のコードを見てみましょう。
logger := logrus.New() logger.Out = os.Stdout // 標準出力 // またはファイルにリダイレクト // out, err := os.OpenFile("file.log", os.O_CREATE|os.O_WRONLY, 0666) // if err != nil { // panic(err) // } // logger.Out = out
Logger struct の定義は次のとおりです。
type Logger struct { Out io.Writer Hooks LevelHooks Formatter Formatter // その他のフィールド... }
重要なプロパティは Out
で、その型は io.Writer
です。このプロパティは、ログ出力ターゲット (標準出力、ファイル、または別のカスタム出力メディア) を指定するために使用されます。
zap ログ記録ライブラリ
zap は、パフォーマンスの高いログ記録ライブラリです。構造化されたログ記録、マルチレベルのログ制御、および柔軟な構成オプションを提供します。
locus と同様に、zap でも構成を介してログ出力場所を決定できますが、実装はわずかに異なります。zap では、ログ出力は zapcore.Core
を介して構成されます。zapcore.Core
のインスタンスを作成するときは、zapcore.WriteSyncer
インターフェイスの実装をパラメータとして指定する必要があります。これにより、ログ出力のターゲットが直接決定されます。zapcore.WriteSyncer
インスタンスを作成するには、通常、zapcore.AddSync()
関数を使用します。この関数は、io.Writer
型のパラメータを受け取ります。
zap を使用してログインスタンスを作成する基本的な例を次に示します。
writer := zapcore.AddSync(os.Stdout) // ログターゲットとして標準出力を使用 core := zapcore.NewCore( zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig()), writer, zap.InfoLevel, ) logger := zap.New(core) defer logger.Sync() // バッファされたログエントリをフラッシュ // ロガーを使用してログを記録
重要なのは zapcore.AddSync()
関数で、io.Writer
型のパラメータを受け取ります。これは、ログ出力ターゲット (標準出力、ファイル、または別のカスタム出力メディア) を指定するために使用されます。
slog ログ記録ライブラリ
slog は、Go 1.21.0 で導入された公式のログ記録ライブラリで、構造化されたログ記録を提供します。slog ログ記録ライブラリの詳細については、以前の記事をご覧ください。
locus および zap と同様に、slog では、io.Writer
パラメータを提供して、ログ出力ターゲットを指定することもできます。この設定は、slog.Handler
インターフェイスの実装を作成するときに行われます。
textLogger := slog.New(slog.NewTextHandler(os.Stdout, nil)) jsonLogger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
これらの 2 つの関数では、slog.NewTextHandler
と slog.NewJSONHandler
の最初のパラメータは io.Writer
型です。
分析のまとめ
logrus、zap、slog という 3 つの主流のログ記録ライブラリの分析から、重要な共通点が見られました。ログ出力を処理する場合、それらはすべて io.Writer
インターフェイスに依存しています。これらのログ記録ライブラリは、io.Writer
インターフェイスを重要なパラメータの型として使用して、ログ出力のターゲットを設定できるようにします。
ログのローテーションと分割の実装メカニズムと実践
実装メカニズム
logrus、zap、slog の設計を分析した後、それらの共通点を発見しました。次に、ログのローテーションと分割のメカニズムについて詳しく見ていきましょう。
ログファイルのローテーションと分割を実装するには、通常、lumberjack などのサードパーティライブラリを利用します。もちろん、他にも同様のライブラリがありますが、ここではすべてをリストしません。
lumberjack は、ログのローテーションと分割のために特別に設計されたライブラリです。その機能は、プラグ可能なコンポーネントに似ています。このコンポーネントを構成し、選択したログ記録ライブラリと統合することで、ログファイルのローテーションと分割を実現できます。
lumberjack コンポーネントを初期化するコードを次に示します。
log := &lumberjack.Logger{ Filename: "/path/file.log", // ログファイルの場所 MaxSize: 10, // 最大ファイルサイズ (MB 単位) MaxBackups: 3, // 保持する古いファイルの最大数 MaxAge: 28, // 古いファイルを保持する最大日数 Compress: true, // 古いファイルを圧縮/アーカイブするかどうか LocalTime: true, // タイムスタンプに現地時間を使用 }
この例では、lumberjack.Logger
インスタンスを作成し、次のパラメータを設定します。
- Filename: ログファイルの保存場所を指定します。
- MaxSize: ファイルがこの MB に達すると、ローテーションされます。
- MaxBackups: 保持する古いログファイルの最大数。
- MaxAge: 古いファイルの最大保持期間 (日数)。
- Compress: 古いファイルを圧縮するかどうか (たとえば、.gz に変換)。
lumberjack の Logger
struct が io.Writer
インターフェイスを実装していることに注意することが重要です。これは、ログファイルのローテーションと分割のすべてのコアロジックが Write
メソッド内にカプセル化されていることを意味します。この実装により、io.Writer
パラメータをサポートするすべてのログ記録ライブラリに Logger struct を簡単に統合できます。
これを理解すると、ログのローテーションと分割を実装する方法はすでにわかります。lumberjack の logger struct は io.Writer
インターフェイスを実装しているため、サードパーティライブラリに渡すと、統合と構成を完了できます。
実践
logrus ログ記録ライブラリを使用した実装
log := &lumberjack.Logger{ Filename: "/path/file.log", // ログファイルの場所 MaxSize: 10, // 最大ファイルサイズ (MB 単位) MaxBackups: 3, // 保持する古いファイルの最大数 MaxAge: 28, // 古いファイルを保持する最大日数 Compress: true, // 古いファイルを圧縮/アーカイブするかどうか LocalTime: true, // タイムスタンプに現地時間を使用 } logger := logrus.New() logger.Out = log
zap ログ記録ライブラリを使用した実装
log := &lumberjack.Logger{ Filename: "/path/file.log", // ログファイルの場所 MaxSize: 10, // 最大ファイルサイズ (MB 単位) MaxBackups: 3, // 保持する古いファイルの最大数 MaxAge: 28, // 古いファイルを保持する最大日数 Compress: true, // 古いファイルを圧縮/アーカイブするかどうか LocalTime: true, // タイムスタンプに現地時間を使用 } writer := zapcore.AddSync(log) core := zapcore.NewCore( zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig()), writer, zap.InfoLevel, ) logger := zap.New(core) defer logger.Sync() // バッファされたログエントリをフラッシュ
slog ログ記録ライブラリを使用した実装
log := &lumberjack.Logger{ Filename: "/path/file.log", // ログファイルの場所 MaxSize: 10, // 最大ファイルサイズ (MB 単位) MaxBackups: 3, // 保持する古いファイルの最大数 MaxAge: 28, // 古いファイルを保持する最大日数 Compress: true, // 古いファイルを圧縮/アーカイブするかどうか LocalTime: true, // タイムスタンプに現地時間を使用 } textLogger := slog.New(slog.NewTextHandler(log, nil)) jsonLogger := slog.New(slog.NewJSONHandler(log, nil))
結論
この記事では、logrus、zap、slog の 3 つの一般的なログ記録ライブラリの設計要素について簡単に分析しました。ログインスタンスの作成方法の詳細は異なりますが、すべて io.Writer
インターフェイスパラメータに依存してログ出力を処理していることがわかりました。io.Writer
パラメータの構成方法を習得し、lumberjack ライブラリと組み合わせることで、ログファイルのローテーションと分割を実現できます。
今後、新しいログ記録ライブラリが導入された場合でも、同様の方法を使用してログファイルのローテーションと分割を迅速に統合できます。
Leapcell は、Go プロジェクトのホスティングに最適な選択肢です。
Leapcell は、Web ホスティング、非同期タスク、Redis のための次世代サーバーレス プラットフォームです。
多言語サポート
- Node.js、Python、Go、または Rust で開発します。
無制限のプロジェクトを無料でデプロイ
- 使用量に対してのみ支払い — リクエストも請求もありません。
比類のないコスト効率
- アイドル料金なしの従量課金制。
- 例: 平均応答時間 60ms で 694 万件のリクエストを 25 ドルでサポートします。
合理化された開発者エクスペリエンス
- 簡単なセットアップのための直感的な UI。
- 完全に自動化された CI/CD パイプラインと GitOps 統合。
- 実用的な洞察のためのリアルタイムのメトリックとログ記録。
簡単なスケーラビリティと高いパフォーマンス
- 高い同時実行性を容易に処理するための自動スケーリング。
- 運用上のオーバーヘッドはゼロ — 構築に集中するだけです。
ドキュメントで詳細をご覧ください!
X でフォローしてください: @LeapcellHQ