Documentation
¶
Overview ¶
slogパッケージは、メッセージ、重大度レベル、およびキー-値ペアとして表されるさまざまなその他の属性を含むログレコードを提供する構造化されたログを提供します。
Logger という型を定義し、 Logger.Info や Logger.Error などのいくつかのメソッドを提供して、 興味深いイベントを報告するための構造化されたログを提供します。
各Loggerは Handler に関連付けられています。 Loggerの出力メソッドは、メソッド引数から Record を作成し、 それを処理する方法を決定するHandlerに渡します。 対応するLoggerメソッドを呼び出す Info や Error などのトップレベル関数を介してアクセス可能なデフォルトのLoggerがあります。
ログレコードは、時刻、レベル、メッセージ、およびキー-値ペアのセットで構成されます。 キーは文字列で、値は任意の型である場合があります。 例として、
slog.Info("hello", "count", 3)
呼び出しの時間、Infoレベル、メッセージ"hello"、および単一のキー"count"と値3を持つレコードを作成します。
Info トップレベル関数は、デフォルトのLogger上の Logger.Info メソッドを呼び出します。 Logger.Info に加えて、Debug、Warn、Errorレベルのメソッドがあります。 これらの一般的なレベルのための便利なメソッドに加えて、 Logger.Log メソッドがあり、レベルを引数として受け取ります。 これらのメソッドのそれぞれに対応するトップレベル関数があり、 デフォルトのロガーを使用します。
デフォルトのハンドラは、ログレコードのメッセージ、時刻、レベル、および属性を 文字列としてフォーマットし、 log パッケージに渡します。
2022/11/08 15:28:26 INFO hello count=3
出力フォーマットをより細かく制御するには、別のハンドラを持つロガーを作成します。 このステートメントでは、 New を使用して、 TextHandler で構造化されたレコードをテキスト形式で標準エラーに書き込む新しいロガーを作成しています。
logger := slog.New(slog.NewTextHandler(os.Stderr, nil))
TextHandler の出力は、キー=値のペアのシーケンスであり、機械によって簡単かつ曖昧に解析できます。 この文:
logger.Info("hello", "count", 3)
は、次の出力を生成します。
time=2022-11-08T15:28:26.000-05:00 level=INFO msg=hello count=3
パッケージはまた、行区切りJSONで出力される JSONHandler を提供します。
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil)) logger.Info("hello", "count", 3)
次の出力を生成します:
{"time":"2022-11-08T15:28:26.000000000-05:00","level":"INFO","msg":"hello","count":3}
TextHandler と JSONHandler の両方は、 HandlerOptions で構成できます。 最小レベルの設定(以下の [Levels] を参照)、 ログ呼び出しのソースファイルと行の表示、 およびログに記録される前に属性を変更するためのオプションがあります。
デフォルトのロガーは以下のようにして変更できます。
slog.SetDefault(logger)
Info のようなトップレベルの関数がloggerを使用するようになります。 SetDefault は、 log パッケージが使用するデフォルトのロガーも更新します。 これにより log.Printf などを使用する既存のアプリケーションが、 書き換える必要なくログレコードをロガーのハンドラに送信できます。
多くのログ呼び出しで共通の属性があります。 たとえば、サーバーリクエストから生じるすべてのログイベントにURLやトレース識別子を含めたい場合があります。 ログ呼び出しごとに属性を繰り返す代わりに、 Logger.With を使用して属性を含む新しいLoggerを構築できます。
logger2 := logger.With("url", r.URL)
Withの引数は、 Logger.Info で使用されるキー-値ペアと同じです。 結果は、元のハンドラと同じハンドラを持つ新しいLoggerですが、 すべての呼び出しの出力に表示される追加の属性が含まれています。
Levels ¶
Level は、ログイベントの重要度または深刻度を表す整数です。 レベルが高いほど、イベントはより深刻です。 このパッケージは、最も一般的なレベルの定数を定義していますが、 任意のintをレベルとして使用できます。
アプリケーションでは、特定のレベル以上のメッセージのみをログに記録することが望ましい場合があります。 一般的な構成の1つは、Infoレベル以上のメッセージをログに記録し、 デバッグログを必要になるまで抑制することです。 組み込みのハンドラは、 [HandlerOptions.Level] を設定することで、 出力する最小レベルを構成できます。 通常、プログラムの`main`関数がこれを行います。 デフォルト値はLevelInfoです。
[HandlerOptions.Level] フィールドを Level 値に設定すると、 ハンドラの最小レベルがその寿命全体で固定されます。 LevelVar に設定すると、レベルを動的に変化させることができます。 LevelVarはLevelを保持し、複数のゴルーチンから読み書きすることができます。 プログラム全体でレベルを動的に変化させるには、まずグローバルなLevelVarを初期化します。
var programLevel = new(slog.LevelVar) // Info by default
次に、LevelVarを使用してハンドラを構築し、デフォルトにします。
h := slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{Level: programLevel}) slog.SetDefault(slog.New(h))
プログラムは、単一のステートメントでログレベルを変更できるようになりました。
programLevel.Set(slog.LevelDebug)
Groups ¶
属性はグループに集めることができます。 グループには、属性の名前に修飾子として使用される名前があります。 この修飾子がどのように表示されるかは、ハンドラによって異なります。 TextHandler は、グループと属性名をドットで区切ります。 JSONHandler は、各グループを別々のJSONオブジェクトとして扱い、グループ名をキーとして扱います。
Group を使用して、名前とキー値のリストからグループ属性を作成します。
slog.Group("request", "method", r.Method, "url", r.URL)
TextHandler は、このグループを次のように表示します。
request.method=GET request.url=http://example.com
JSONHandler は、次のように表示します。
"request":{"method":"GET","url":"http://example.com"}
Logger.WithGroup を使用して、Loggerのすべての出力にグループ名を付けます。 LoggerでWithGroupを呼び出すと、元のハンドラと同じハンドラを持つ新しいLoggerが生成されますが、すべての属性がグループ名で修飾されます。
これにより、大規模なシステムで重複した属性キーを防止できます。 サブシステムが同じキーを使用する可能性がある場合、異なるグループ名を持つ独自のLoggerを各サブシステムに渡して、潜在的な重複を修飾します。
logger := slog.Default().With("id", systemID) parserLogger := logger.WithGroup("parser") parseInput(input, parserLogger)
parseInputがparserLoggerでログを記録する場合、そのキーは "parser"で修飾されるため、共通のキー "id"を使用していても、ログ行には異なるキーがあります。
Contexts ¶
一部のハンドラは、呼び出し元で利用可能な context.Context から情報を取得することを望む場合があります。 トレースが有効になっている場合、現在のスパンの識別子などの情報が含まれます。
Logger.Log と Logger.LogAttrs メソッドは、対応するトップレベル関数と同様に、最初の引数としてコンテキストを取ります。
Loggerの便利なメソッド(Infoなど)と対応するトップレベル関数は、コンテキストを取りませんが、"Context"で終わる代替メソッドはコンテキストを取ります。例えば、
slog.InfoContext(ctx, "message")
出力メソッドにコンテキストが利用可能な場合は、コンテキストを渡すことをお勧めします。
Attrs and Values ¶
Attr は、キーと値のペアです。Loggerの出力メソッドは、Attrsと交互にキーと値を受け入れます。以下の文を参照してください。
slog.Info("hello", slog.Int("count", 3))
以下のように動作します。
slog.Info("hello", "count", 3)
Attr には Int 、 String 、 Bool などの便利なコンストラクタがあり、一般的な型に対して、 Any 関数を使用して任意の型の Attr を構築することもできます。
Attr の値部分は Value と呼ばれる型です。 [any] のように、 Value は任意のGo値を保持できますが、 すべての数値と文字列を含む一般的な値を、割り当てなしで表現できます。
最も効率的なログ出力には、 Logger.LogAttrs を使用してください。 これは Logger.Log に似ていますが、交互にキーと値を受け入れるのではなく、Attrsのみを受け入れるため、これも割り当てを回避できます。
logger.LogAttrs(ctx, slog.LevelInfo, "hello", slog.Int("count", 3))
は、以下と同じ出力を生成する最も効率的な方法です。
slog.Info("hello", "count", 3)
slog.InfoContext(ctx, "hello", "count", 3)
Customizing a type's logging behavior ¶
タイプが LogValuer インターフェースを実装している場合、その [LogValue] メソッドから返される Value がログ出力に使用されます。 これを使用して、タイプの値がログにどのように表示されるかを制御できます。 例えば、パスワードのような秘密情報を伏せたり、構造体のフィールドをグループ化したりすることができます。 詳細については、 LogValuer の例を参照してください。
LogValueメソッドは、 LogValuer を実装している Value を返すことができます。 Value.Resolve メソッドは、これらの場合に無限ループや無制限の再帰を回避するように注意して処理します。 ハンドラの作者やその他の人々は、LogValueを直接呼び出す代わりに、Value.Resolve を使用したい場合があります。
Wrapping output methods ¶
ロガー関数は、呼び出し元のコールスタック上でリフレクションを使用して、アプリケーション内のログ呼び出しのファイル名と行番号を検索します。 これは、slogをラップする関数に対して誤ったソース情報を生成する可能性があります。 たとえば、mylog.goファイルでこの関数を定義する場合、以下のようになります。
func Infof(logger *slog.Logger, format string, args ...any) { logger.Info(fmt.Sprintf(format, args...)) }
そして、main.goで次のように呼び出す場合、
Infof(slog.Default(), "hello, %s", "world")
slogは、ソースファイルをmylog.goではなくmain.goとして報告しません。
Infofの正しい実装は、ソースの場所(pc)を取得し、NewRecordに渡す必要があります。 パッケージレベルの例である "wrapping" で示されているように、Infof関数の実装方法を示します。
Working with Records ¶
ハンドラが別のハンドラやバックエンドに渡す前に、レコードを変更する必要がある場合があります。 レコードには、単純な公開フィールド(例: Time、Level、Message)と、状態(属性など)を間接的に参照する非公開フィールドが混在しています。 これは、レコードの単純なコピーを変更する(例えば、属性を追加するために Record.Add または Record.AddAttrs を呼び出す)と、元のレコードに予期しない影響を与える可能性があることを意味します。 レコードを変更する前に、 Record.Clone を使用して、元のレコードと状態を共有しないコピーを作成するか、 NewRecord で新しいレコードを作成し、 Record.Attrs を使用して古いレコードをトラバースしてそのAttrsを構築してください。
Performance considerations ¶
アプリケーションのプロファイリングによって、ログの記録にかかる時間がかなりあることが示された場合、以下の提案が役立つ場合があります。
多くのログ行に共通の属性がある場合は、 Logger.With を使用して、その属性を持つLoggerを作成します。 組み込みのハンドラは、 Logger.With の呼び出し時にその属性を1回だけフォーマットします。 Handler インターフェースは、その最適化を許容するように設計されており、適切に書かれたHandlerはそれを活用するはずです。
ログ呼び出しの引数は常に評価されます。たとえログイベントが破棄された場合でもです。 可能であれば、値が実際にログに記録される場合にのみ計算が行われるように遅延させてください。 たとえば、次の呼び出しを考えてみてください。
slog.Info("starting request", "url", r.URL.String()) // may compute String unnecessarily
URL.Stringメソッドは、ロガーがInfoレベルのイベントを破棄する場合でも呼び出されます。 代わりに、URLを直接渡してください。
slog.Info("starting request", "url", &r.URL) // calls URL.String only if needed
組み込みの TextHandler は、そのStringメソッドを呼び出しますが、 ログイベントが有効になっている場合にのみ呼び出します。 Stringの呼び出しを回避することは、基礎となる値の構造を保持することもできます。 例えば、 JSONHandler は解析されたURLのコンポーネントをJSONオブジェクトとして出力します。 String呼び出しのコストを支払うことを避けたい場合、 値の構造を検査する可能性のあるハンドラを引き起こすことなく、 その値を隠すfmt.Stringer実装でラップしてください。
LogValuer インターフェースを使用すると、無効なログ呼び出しで不必要な作業を回避できます。 例えば、高価な値をログに記録する必要がある場合を考えてみましょう。
slog.Debug("frobbing", "value", computeExpensiveValue(arg))
この行が無効になっていても、computeExpensiveValueが呼び出されます。 これを回避するには、LogValuerを実装する型を定義します。
type expensive struct { arg int } func (e expensive) LogValue() slog.Value { return slog.AnyValue(computeExpensiveValue(e.arg)) }
そして、ログ呼び出しでその型の値を使用します。
slog.Debug("frobbing", "value", expensive{arg})
これで、行が有効になっている場合にのみcomputeExpensiveValueが呼び出されます。
組み込みのハンドラは、io.Writer.Write を呼び出す前にロックを取得して、 一度に正確に一つの Record が完全に書き込まれることを保証します。 各ログレコードにはタイムスタンプがありますが、 組み込みのハンドラはその時間を使用して書き込まれたレコードをソートしません。 ユーザー定義のハンドラは、自身のロックとソートを担当します。
ハンドラの作成 ¶
カスタムハンドラの作成方法についてのガイドについては、https://golang.org/s/slog-handler-guide を参照してください。
Example (Wrapping) ¶
replace := func(groups []string, a slog.Attr) slog.Attr { // Remove time. if a.Key == slog.TimeKey && len(groups) == 0 { return slog.Attr{} } // Remove the directory from the source's filename. if a.Key == slog.SourceKey { source := a.Value.Any().(*slog.Source) source.File = filepath.Base(source.File) } return a } logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{AddSource: true, ReplaceAttr: replace})) Infof(logger, "message, %s", "formatted")
Output: level=INFO source=example_wrap_test.go:43 msg="message, formatted"
Index ¶
- Constants
- func Debug(msg string, args ...any)
- func DebugContext(ctx context.Context, msg string, args ...any)
- func Error(msg string, args ...any)
- func ErrorContext(ctx context.Context, msg string, args ...any)
- func Info(msg string, args ...any)
- func InfoContext(ctx context.Context, msg string, args ...any)
- func Log(ctx context.Context, level Level, msg string, args ...any)
- func LogAttrs(ctx context.Context, level Level, msg string, attrs ...Attr)
- func NewLogLogger(h Handler, level Level) *log.Logger
- func SetDefault(l *Logger)
- func Warn(msg string, args ...any)
- func WarnContext(ctx context.Context, msg string, args ...any)
- type Attr
- func Any(key string, value any) Attr
- func Bool(key string, v bool) Attr
- func Duration(key string, v time.Duration) Attr
- func Float64(key string, v float64) Attr
- func Group(key string, args ...any) Attr
- func Int(key string, value int) Attr
- func Int64(key string, value int64) Attr
- func String(key, value string) Attr
- func Time(key string, v time.Time) Attr
- func Uint64(key string, v uint64) Attr
- type Handler
- type HandlerOptions
- type JSONHandler
- type Kind
- type Level
- type LevelVar
- type Leveler
- type LogValuer
- type Logger
- func (l *Logger) Debug(msg string, args ...any)
- func (l *Logger) DebugContext(ctx context.Context, msg string, args ...any)
- func (l *Logger) Enabled(ctx context.Context, level Level) bool
- func (l *Logger) Error(msg string, args ...any)
- func (l *Logger) ErrorContext(ctx context.Context, msg string, args ...any)
- func (l *Logger) Handler() Handler
- func (l *Logger) Info(msg string, args ...any)
- func (l *Logger) InfoContext(ctx context.Context, msg string, args ...any)
- func (l *Logger) Log(ctx context.Context, level Level, msg string, args ...any)
- func (l *Logger) LogAttrs(ctx context.Context, level Level, msg string, attrs ...Attr)
- func (l *Logger) Warn(msg string, args ...any)
- func (l *Logger) WarnContext(ctx context.Context, msg string, args ...any)
- func (l *Logger) With(args ...any) *Logger
- func (l *Logger) WithGroup(name string) *Logger
- type Record
- type Source
- type TextHandler
- type Value
- func AnyValue(v any) Value
- func BoolValue(v bool) Value
- func DurationValue(v time.Duration) Value
- func Float64Value(v float64) Value
- func GroupValue(as ...Attr) Value
- func Int64Value(v int64) Value
- func IntValue(v int) Value
- func StringValue(value string) Value
- func TimeValue(v time.Time) Value
- func Uint64Value(v uint64) Value
- func (v Value) Any() any
- func (v Value) Bool() bool
- func (a Value) Duration() time.Duration
- func (v Value) Equal(w Value) bool
- func (v Value) Float64() float64
- func (v Value) Group() []Attr
- func (v Value) Int64() int64
- func (v Value) Kind() Kind
- func (v Value) LogValuer() LogValuer
- func (v Value) Resolve() (rv Value)
- func (v Value) String() string
- func (v Value) Time() time.Time
- func (v Value) Uint64() uint64
Examples ¶
Constants ¶
const ( // TimeKeyは、ログメソッドが呼び出されたときの時間を表すために、 // 組み込みハンドラによって使用されるキーです。 // 関連する値は[time.Time]です。 TimeKey = "time" // LevelKeyは、ログ呼び出しのレベルを表すために、 // 組み込みハンドラによって使用されるキーです。 // 関連する値は[Level]です。 LevelKey = "level" // MessageKeyは、ログ呼び出しのメッセージを表すために、 // 組み込みハンドラによって使用されるキーです。 // 関連する値は文字列です。 MessageKey = "msg" // SourceKey は、ログ呼び出しのソースファイルと行のためにビルトインハンドラによって使用されるキーです。 // 関連する値は *[Source] です。 SourceKey = "source" )
"built-in"属性のキー。
Variables ¶
This section is empty.
Functions ¶
func DebugContext ¶
DebugContextは、デフォルトのロガーで Logger.DebugContext を呼び出します。
func ErrorContext ¶
ErrorContextは、デフォルトのロガーで Logger.ErrorContext を呼び出します。
func InfoContext ¶
InfoContextは、デフォルトのロガーで Logger.InfoContext を呼び出します。
func Log ¶
Logは、デフォルトのロガーで Logger.Log を呼び出します。
func LogAttrs ¶
LogAttrsは、デフォルトのロガーで Logger.LogAttrs を呼び出します。
func NewLogLogger ¶
NewLogLoggerは、指定されたハンドラにRecordをディスパッチするための新しい log.Logger を返します。 ロガーは、古いログAPIから新しい構造化ログハンドラへのブリッジとして機能します。
func SetDefault ¶
func SetDefault(l *Logger)
SetDefault makes l the default Logger, which is used by the top-level functions Info, Debug and so on. After this call, output from the log package's default Logger (as with log.Print, etc.) will be logged using l's Handler, at a level controlled by SetLogLoggerLevel.
func WarnContext ¶
WarnContextは、デフォルトのロガーで Logger.WarnContext を呼び出します。
Types ¶
type Attr ¶
Attrはキーと値のペアです。
func Group ¶
GroupはGroup Value のAttrを返します。 最初の引数はキーで、残りの引数は Logger.Log と同様にAttrsに変換されます。
Groupを使用して、ログ行の単一のキーの下に複数のキー-値ペアを収集するか、 LogValueの結果として単一の値を複数のAttrsとしてログに記録するために使用します。
Example ¶
package main import ( "github.com/shogo82148/std/log/slog" "github.com/shogo82148/std/net/http" "github.com/shogo82148/std/os" "github.com/shogo82148/std/time" ) func main() { r, _ := http.NewRequest("GET", "localhost", nil) // ... logger := slog.New( slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{ ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr { if a.Key == slog.TimeKey && len(groups) == 0 { return slog.Attr{} } return a }, }), ) logger.Info("finished", slog.Group("req", slog.String("method", r.Method), slog.String("url", r.URL.String())), slog.Int("status", http.StatusOK), slog.Duration("duration", time.Second)) }
Output: level=INFO msg=finished req.method=GET req.url=localhost status=200 duration=1s
type Handler ¶
type Handler interface { Enabled(context.Context, Level) bool Handle(context.Context, Record) error WithAttrs(attrs []Attr) Handler WithGroup(name string) Handler }
A Handler handles log records produced by a Logger.
典型的なハンドラは、ログレコードを標準エラーに出力したり、 ファイルやデータベースに書き込んだり、 または追加の属性を追加して別のハンドラに渡すことができます。
Handlerのメソッドのいずれかは、自身または他のメソッドと同時に呼び出される可能性があります。 Handlerは、この並行性を管理する責任があります。
slogパッケージのユーザーは、Handlerメソッドを直接呼び出すべきではありません。 代わりに、[Logger]のメソッドを使用する必要があります。
Example (LevelHandler) ¶
この例では、ログレベルを上げて、ロガーの出力を減らす方法を示しています。
別の一般的な使用方法は、(例えばLevelDebugに)ログレベルを下げて、 バグが含まれていると疑われるプログラムの一部分でログを出力することです。
package main import ( "github.com/shogo82148/std/log/slog" "github.com/shogo82148/std/log/slog/internal/slogtest" "github.com/shogo82148/std/os" ) // A LevelHandler wraps a Handler with an Enabled method // that returns false for levels below a minimum. type LevelHandler struct { level slog.Leveler handler slog.Handler } // この例では、ログレベルを上げて、ロガーの出力を減らす方法を示しています。 // // 別の一般的な使用方法は、(例えばLevelDebugに)ログレベルを下げて、 // バグが含まれていると疑われるプログラムの一部分でログを出力することです。 func main() { th := slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{ReplaceAttr: slogtest.RemoveTime}) logger := slog.New(NewLevelHandler(slog.LevelWarn, th)) logger.Info("not printed") logger.Warn("printed") }
Output: level=WARN msg=printed
type HandlerOptions ¶
type HandlerOptions struct { // AddSource causes the handler to compute the source code position // of the log statement and add a SourceKey attribute to the output. AddSource bool // Level reports the minimum record level that will be logged. // The handler discards records with lower levels. // If Level is nil, the handler assumes LevelInfo. // The handler calls Level.Level for each record processed; // to adjust the minimum level dynamically, use a LevelVar. Level Leveler // ReplaceAttr is called to rewrite each non-group attribute before it is logged. // The attribute's value has been resolved (see [Value.Resolve]). // If ReplaceAttr returns a zero Attr, the attribute is discarded. // // The built-in attributes with keys "time", "level", "source", and "msg" // are passed to this function, except that time is omitted // if zero, and source is omitted if AddSource is false. // // The first argument is a list of currently open groups that contain the // Attr. It must not be retained or modified. ReplaceAttr is never called // for Group attributes, only their contents. For example, the attribute // list // // Int("a", 1), Group("g", Int("b", 2)), Int("c", 3) // // results in consecutive calls to ReplaceAttr with the following arguments: // // nil, Int("a", 1) // []string{"g"}, Int("b", 2) // nil, Int("c", 3) // // ReplaceAttr can be used to change the default keys of the built-in // attributes, convert types (for example, to replace a `time.Time` with the // integer seconds since the Unix epoch), sanitize personal information, or // remove attributes from the output. ReplaceAttr func(groups []string, a Attr) Attr }
HandlerOptionsは、TextHandler または JSONHandler のオプションです。 ゼロ値のHandlerOptionsは、完全にデフォルト値で構成されています。
Example (CustomLevels) ¶
This example demonstrates using custom log levels and custom log level names. In addition to the default log levels, it introduces Trace, Notice, and Emergency levels. The ReplaceAttr changes the way levels are printed for both the standard log levels and the custom log levels.
package main import ( "github.com/shogo82148/std/context" "github.com/shogo82148/std/log/slog" "github.com/shogo82148/std/os" ) func main() { // カスタムログパッケージからエクスポートされた定数。 const ( LevelTrace = slog.Level(-8) LevelDebug = slog.LevelDebug LevelInfo = slog.LevelInfo LevelNotice = slog.Level(2) LevelWarning = slog.LevelWarn LevelError = slog.LevelError LevelEmergency = slog.Level(12) ) th := slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{ // すべてのログ出力を表示するために、カスタムレベルを設定します。 // デフォルト値はLevelInfoであり、DebugとTraceログをドロップします。 Level: LevelTrace, ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr { // 予測可能なテスト出力のために、出力から時間を削除します。 if a.Key == slog.TimeKey { return slog.Attr{} } // レベルキーの名前と出力文字列をカスタマイズします。 // カスタムレベル値を含みます。 if a.Key == slog.LevelKey { // レベルキーを "level" から "sev" に変更します。 a.Key = "sev" // カスタムレベル値を処理します。 level := a.Value.Any().(slog.Level) // これはマップや他の構造から名前を検索することもできますが、 // この例ではswitch文を使用してレベルをリネームする方法を示しています。 // 文字列値は定数であるべきですが、可読性のためにこの例では生の文字列を使用しています。 switch { case level < LevelDebug: a.Value = slog.StringValue("TRACE") case level < LevelInfo: a.Value = slog.StringValue("DEBUG") case level < LevelNotice: a.Value = slog.StringValue("INFO") case level < LevelWarning: a.Value = slog.StringValue("NOTICE") case level < LevelError: a.Value = slog.StringValue("WARNING") case level < LevelEmergency: a.Value = slog.StringValue("ERROR") default: a.Value = slog.StringValue("EMERGENCY") } } return a }, }) logger := slog.New(th) ctx := context.Background() logger.Log(ctx, LevelEmergency, "missing pilots") logger.Error("failed to start engines", "err", "missing fuel") logger.Warn("falling back to default value") logger.Log(ctx, LevelNotice, "all systems are running") logger.Info("initiating launch") logger.Debug("starting background job") logger.Log(ctx, LevelTrace, "button clicked") }
Output: sev=EMERGENCY msg="missing pilots" sev=ERROR msg="failed to start engines" err="missing fuel" sev=WARNING msg="falling back to default value" sev=NOTICE msg="all systems are running" sev=INFO msg="initiating launch" sev=DEBUG msg="starting background job" sev=TRACE msg="button clicked"
type JSONHandler ¶
type JSONHandler struct {
// contains filtered or unexported fields
}
JSONHandlerは、レコードを行区切りのJSONオブジェクトとして io.Writer に書き込む Handler です。
func NewJSONHandler ¶
func NewJSONHandler(w io.Writer, opts *HandlerOptions) *JSONHandler
NewJSONHandlerは、指定されたオプションを使用して、 wに書き込む JSONHandler を作成します。 optsがnilの場合、デフォルトのオプションが使用されます。
func (*JSONHandler) Enabled ¶
func (h *JSONHandler) Enabled(_ context.Context, level Level) bool
Enabledは、ハンドラが指定されたレベルのレコードを処理するかどうかを報告します。 ハンドラは、レベルが低いレコードを無視します。
func (*JSONHandler) Handle ¶
func (h *JSONHandler) Handle(_ context.Context, r Record) error
Handleは、引数の Record をJSONオブジェクトとして1行にフォーマットします。
Recordの時間がゼロの場合、時間は省略されます。 そうでない場合、キーは "time" であり、値はjson.Marshalと同様に出力されます。
Recordのレベルがゼロの場合、レベルは省略されます。 そうでない場合、キーは "level" であり、 Level.String の値が出力されます。
AddSourceオプションが設定されており、ソース情報が利用可能な場合、 キーは "source" であり、値は Source 型のレコードです。
メッセージのキーは "msg" です。
これらまたは他の属性を変更したり、出力から削除したりするには、 [HandlerOptions.ReplaceAttr] を使用します。
値は、SetEscapeHTML(false)を使用して encoding/json.Encoder と同様にフォーマットされます。 ただし、2つの例外があります。
最初に、値がエラー型であるAttrは、そのErrorメソッドを呼び出すことによって文字列としてフォーマットされます。 この特別な処理は、encoding/json パッケージによって処理される構造体、スライス、マップ、その他のデータ構造に埋め込まれたエラーではなく、 Attrs内のエラーのみが受け取ります。
2つ目は、エンコードの失敗がHandleからエラーを返すことはありません。 代わりに、エラーメッセージが文字列としてフォーマットされます。
Handleの各呼び出しは、io.Writer.Writeに対して1回のシリアル化された呼び出しを生成します。
func (*JSONHandler) WithAttrs ¶
func (h *JSONHandler) WithAttrs(attrs []Attr) Handler
WithAttrsは、hの属性に続く属性で構成される新しい JSONHandler を返します。
func (*JSONHandler) WithGroup ¶
func (h *JSONHandler) WithGroup(name string) Handler
type Level ¶
type Level int
Levelは、ログイベントの重要度または深刻度を表します。 レベルが高いほど、イベントはより重要または深刻です。
一般的なレベルの名前。
レベル番号は本質的に任意ですが、3つの制約を満たすように選択しました。 任意のシステムは、別の番号付けスキームにマップできます。
まず、デフォルトのレベルをInfoにしたかったため、Levelsはintであり、 Infoはintのデフォルト値であるゼロです。
2番目に、レベルを使用してロガーの冗長性を指定することを簡単にしたかったです。 より深刻なイベントは、より高いレベルを意味するため、 より小さい(または負の)レベルのイベントを受け入れるロガーは、より冗長なロガーを意味します。 ロガーの冗長性は、したがってイベントの深刻度の否定であり、 デフォルトの冗長性0は、INFO以上のすべてのイベントを受け入れます。
3番目に、名前付きレベルを持つスキームを収容するために、レベル間に余裕が必要でした。 たとえば、Google Cloud Loggingは、InfoとWarnの間にNoticeレベルを定義しています。 これらの中間レベルはわずかであるため、数字の間のギャップは大きくする必要はありません。 私たちのギャップ4はOpenTelemetryのマッピングに一致します。 OpenTelemetryのDEBUG、INFO、WARN、ERROR範囲から9を引くと、 対応するslog Level範囲に変換されます。 OpenTelemetryにはTRACEとFATALという名前がありますが、slogにはありません。 ただし、適切な整数を使用することで、これらのOpenTelemetryレベルをslog Levelsとして表すことができます。
func SetLogLoggerLevel ¶ added in v1.22.0
SetLogLoggerLevelは、log パッケージへのブリッジのレベルを制御します。
SetDefault が呼び出される前は、slogのトップレベルのログ関数はデフォルトの log.Logger を呼び出します。 そのモードでは、SetLogLoggerLevelはそれらの呼び出しの最小レベルを設定します。 デフォルトでは、最小レベルはInfoなので、Debug への呼び出し (およびより低いレベルでのトップレベルのログ呼び出し) はlog.Loggerに渡されません。次の呼び出し後
slog.SetLogLoggerLevel(slog.LevelDebug)
Debug への呼び出しはlog.Loggerに渡されます。
SetDefault が呼び出された後、デフォルトの log.Logger への呼び出しは slogのデフォルトハンドラーに渡されます。そのモードでは、 SetLogLoggerLevelはそれらの呼び出しがログに記録されるレベルを設定します。 つまり、次の呼び出し後
slog.SetLogLoggerLevel(slog.LevelDebug)
[log.Printf]への呼び出しは、LevelDebug レベルでの出力を結果とします。
SetLogLoggerLevelは前の値を返します。
Example (Log) ¶
This example shows how to use slog.SetLogLoggerLevel to change the minimal level of the internal default handler for slog package before calling slog.SetDefault.
package main import ( "github.com/shogo82148/std/log" "github.com/shogo82148/std/log/slog" "github.com/shogo82148/std/os" ) func main() { defer log.SetFlags(log.Flags()) // revert changes after the example log.SetFlags(0) defer log.SetOutput(log.Writer()) // revert changes after the example log.SetOutput(os.Stdout) // Default logging level is slog.LevelInfo. log.Print("log debug") // log debug slog.Debug("debug") // no output slog.Info("info") // INFO info // Set the default logging level to slog.LevelDebug. currentLogLevel := slog.SetLogLoggerLevel(slog.LevelDebug) defer slog.SetLogLoggerLevel(currentLogLevel) // revert changes after the example log.Print("log debug") // log debug slog.Debug("debug") // DEBUG debug slog.Info("info") // INFO info }
Output: log debug INFO info log debug DEBUG debug INFO info
Example (Slog) ¶
This example shows how to use slog.SetLogLoggerLevel to change the minimal level of the internal writer that uses the custom handler for log package after calling slog.SetDefault.
package main import ( "github.com/shogo82148/std/log" "github.com/shogo82148/std/log/slog" "github.com/shogo82148/std/log/slog/internal/slogtest" "github.com/shogo82148/std/os" ) func main() { // Set the default logging level to slog.LevelError. currentLogLevel := slog.SetLogLoggerLevel(slog.LevelError) defer slog.SetLogLoggerLevel(currentLogLevel) // revert changes after the example defer slog.SetDefault(slog.Default()) // revert changes after the example slog.SetDefault(slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{ReplaceAttr: slogtest.RemoveTime}))) log.Print("error") // level=ERROR msg=error }
Output: level=ERROR msg=error
func (Level) MarshalJSON ¶
MarshalJSONは、 Level.String の出力を引用符で囲んで、 encoding/json.Marshaler を実装します。
func (Level) MarshalText ¶
MarshalTextは、 Level.String を呼び出して、 encoding.TextMarshaler を実装します。
func (Level) String ¶
Stringは、レベルの名前を返します。 レベルに名前がある場合、その名前を大文字で返します。 レベルが名前付き値の間にある場合、 大文字の名前に整数が追加されます。 例:
LevelWarn.String() => "WARN" (LevelInfo+2).String() => "INFO+2"
func (*Level) UnmarshalJSON ¶
UnmarshalJSONは、 encoding/json.Unmarshaler を実装します。 Level.MarshalJSON によって生成された任意の文字列を受け入れ、 大文字小文字を区別しません。 また、出力上異なる文字列になる数値オフセットも受け入れます。 たとえば、"Error-8"は "INFO" としてマーシャルされます。
func (*Level) UnmarshalText ¶
UnmarshalTextは、 encoding.TextUnmarshaler を実装します。 Level.MarshalText によって生成された任意の文字列を受け入れ、 大文字小文字を区別しません。 また、出力上異なる文字列になる数値オフセットも受け入れます。 たとえば、"Error-8"は "INFO" としてマーシャルされます。
type LevelVar ¶
type LevelVar struct {
// contains filtered or unexported fields
}
LevelVarは、Level 変数を表し、Handler レベルを動的に変更するために使用されます。 Leveler を実装すると同時に、Setメソッドも実装しており、 複数のゴルーチンから使用することができます。 ゼロ値のLevelVarは LevelInfo に対応します。
func (*LevelVar) MarshalText ¶
MarshalTextは、 Level.MarshalText を呼び出して、 encoding.TextMarshaler を実装します。
func (*LevelVar) UnmarshalText ¶
UnmarshalTextは、 Level.UnmarshalText を呼び出して、 encoding.TextUnmarshaler を実装します。
type Leveler ¶
type Leveler interface {
Level() Level
}
Levelerは、Level 値を提供します。
Level自体がLevelerを実装しているため、 HandlerOptions など、Levelerが必要な場所では通常、Level値を提供します。 レベルを動的に変更する必要があるクライアントは、 *[LevelVar]などのより複雑なLeveler実装を提供できます。
type LogValuer ¶
type LogValuer interface {
LogValue() Value
}
LogValuerは、自身をログ出力するためにValueに変換できる任意のGo値です。
このメカニズムは、高価な操作を必要になるまで遅延させるために使用できます。 また、単一の値を複数のコンポーネントに展開するために使用できます。
Example (Group) ¶
n := Name{"Perry", "Platypus"} slog.Info("mission accomplished", "agent", n) // JSON Output would look in part like: // { // ... // "msg": "mission accomplished", // "agent": { // "first": "Perry", // "last": "Platypus" // } // }
Output:
Example (Secret) ¶
この例では、自身を置き換えるValueを使用して、秘密を明らかにしないようにする方法を示します。
package main import ( "github.com/shogo82148/std/log/slog" "github.com/shogo82148/std/log/slog/internal/slogtest" "github.com/shogo82148/std/os" ) // A token is a secret value that grants permissions. type Token string // この例では、自身を置き換えるValueを使用して、秘密を明らかにしないようにする方法を示します。 func main() { t := Token("shhhh!") logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{ReplaceAttr: slogtest.RemoveTime})) logger.Info("permission granted", "user", "Perry", "token", t) }
Output: level=INFO msg="permission granted" user=Perry token=REDACTED_TOKEN
type Logger ¶
type Logger struct {
// contains filtered or unexported fields
}
Loggerは、各Log、Debug、Info、Warn、Errorメソッドの呼び出しについて、 構造化された情報を記録します。 各呼び出しに対して、Record を作成し、Handler に渡します。
新しいLoggerを作成するには、[New]または"With"で始まるLoggerメソッドを呼び出します。
func (*Logger) DebugContext ¶
DebugContextは、指定されたコンテキストで LevelDebug でログを記録します。
func (*Logger) ErrorContext ¶
ErrorContextは、指定されたコンテキストで LevelError でログを記録します。
func (*Logger) InfoContext ¶
InfoContextは、指定されたコンテキストで LevelInfo でログを記録します。
func (*Logger) Log ¶
Logは、現在の時刻と指定されたレベルとメッセージでログレコードを生成します。 RecordのAttrsは、Loggerの属性に続くAttrsで構成されます。
属性引数は、次のように処理されます。
- 引数がAttrの場合、そのまま使用されます。
- 引数が文字列で、これが最後の引数でない場合、 次の引数が値として扱われ、2つがAttrに結合されます。
- それ以外の場合、引数はキー "!BADKEY" を持つ値として扱われます。
func (*Logger) WarnContext ¶
WarnContextは、指定されたコンテキストで LevelWarn でログを記録します。
type Record ¶
type Record struct { // The time at which the output method (Log, Info, etc.) was called. Time time.Time // The log message. Message string // The level of the event. Level Level // The program counter at the time the record was constructed, as determined // by runtime.Callers. If zero, no program counter is available. // // The only valid use for this value is as an argument to // [runtime.CallersFrames]. In particular, it must not be passed to // [runtime.FuncForPC]. PC uintptr // contains filtered or unexported fields }
Recordは、ログイベントに関する情報を保持します。 Recordのコピーは状態を共有します。 Recordをコピーしてから変更しないでください。 新しいRecordを作成するには、 NewRecord を呼び出します。 共有状態のないコピーを作成するには、 Record.Clone を使用します。
func NewRecord ¶
NewRecordは、指定された引数から Record を作成します。 Recordに属性を追加するには、 Record.AddAttrs を使用します。
NewRecordは、 Handler をバックエンドとしてサポートするログAPIに使用することを想定しています。
func (*Record) Add ¶
Addは、[Logger.Log]で説明されているように、argsをAttrsに変換し、 Record のAttrsリストにAttrsを追加します。 空のグループは省略されます。
type Source ¶
type Source struct { // Function is the package path-qualified function name containing the // source line. If non-empty, this string uniquely identifies a single // function in the program. This may be the empty string if not known. Function string `json:"function"` // File and Line are the file name and line number (1-based) of the source // line. These may be the empty string and zero, respectively, if not known. File string `json:"file"` Line int `json:"line"` }
Sourceは、ソースコードの行の場所を記述します。
type TextHandler ¶
type TextHandler struct {
// contains filtered or unexported fields
}
TextHandlerは、io.Writer にkey=valueペアのシーケンスと改行を続けて書き込むHandlerです。
func NewTextHandler ¶
func NewTextHandler(w io.Writer, opts *HandlerOptions) *TextHandler
NewTextHandlerは、指定されたオプションを使用して、wに書き込む TextHandler を作成します。 optsがnilの場合、デフォルトのオプションが使用されます。
func (*TextHandler) Enabled ¶
func (h *TextHandler) Enabled(_ context.Context, level Level) bool
Enabledは、ハンドラが指定されたレベルのレコードを処理するかどうかを報告します。 ハンドラは、レベルが低いレコードを無視します。
func (*TextHandler) Handle ¶
func (h *TextHandler) Handle(_ context.Context, r Record) error
Handleは、引数 Record をスペースで区切られたkey=valueの1行としてフォーマットします。
Recordのtimeがゼロの場合、timeは省略されます。 そうでない場合、keyは"time"であり、RFC3339形式でミリ秒精度で出力されます。
Recordのlevelがゼロの場合、levelは省略されます。 そうでない場合、keyは"level"であり、 Level.String の値が出力されます。
AddSourceオプションが設定されており、ソース情報が利用可能な場合、 keyは"source"であり、値はFILE:LINEとして出力されます。
メッセージのkeyは"msg"です。
これらまたは他の属性を変更したり、出力から削除するには、 [HandlerOptions.ReplaceAttr] を使用します。
値が encoding.TextMarshaler を実装している場合、MarshalTextの結果が書き込まれます。 そうでない場合、fmt.Sprint の結果が書き込まれます。
キーと値は、Unicodeスペース文字、非表示文字、'"'、'='を含む場合、 strconv.Quote で引用符で囲まれます。
グループ内のキーは、ドットで区切られたコンポーネント(キーまたはグループ名)で構成されます。 さらにエスケープは行われません。 したがって、キー"a.b.c"から、2つのグループ"a"と"b"とキー"c"があるか、 単一のグループ"a.b"とキー"c"があるか、単一のグループ"a"とキー"b.c"があるかを判断する方法はありません。 コンポーネント内にドットがある場合でも、キーのグループ構造を再構築する必要がある場合は、 [HandlerOptions.ReplaceAttr] を使用して、その情報をキーにエンコードします。
Handleの各呼び出しは、io.Writer.Writeへの単一のシリアル化された呼び出しの結果を返します。
func (*TextHandler) WithAttrs ¶
func (h *TextHandler) WithAttrs(attrs []Attr) Handler
WithAttrsは、hの属性に続くattrsで構成される新しい TextHandler を返します。
func (*TextHandler) WithGroup ¶
func (h *TextHandler) WithGroup(name string) Handler
type Value ¶
type Value struct {
// contains filtered or unexported fields
}
Valueは、任意のGo値を表すことができますが、type anyとは異なり、 大部分の小さな値を割り当てなしで表現できます。 ゼロ値のValueはnilに対応します。
func AnyValue ¶
AnyValueは、提供された値の Value を返します。
提供された値がValue型の場合、変更されずに返されます。
Goの事前宣言されたstring、bool、または(非複素)数値型のいずれかの値が与えられた場合、 AnyValueは、KindString、KindBool、KindUint64、KindInt64、または KindFloat64 の種類のValueを返します。 元の数値型の幅は保持されません。
time.Time または time.Duration 値が与えられた場合、AnyValueは、KindTime または KindDuration のValueを返します。 monotonic timeは保持されません。
nil、または数値型の基礎型である名前付き型を含む、すべての他の型の値の場合、 AnyValueは、KindAny の種類のValueを返します。
func DurationValue ¶
DurationValueは、time.Duration の Value を返します。
func GroupValue ¶
GroupValueは、Attrのリストの新しい Value を返します。 呼び出し元は、引数スライスを後で変更しないでください。
func (Value) Duration ¶
Durationは、vの値をtime.Durationとして返します。vが time.Duration でない場合はpanicします。
func (Value) Resolve ¶
Resolveは、vが LogValuer を実装している間、vのLogValueを繰り返し呼び出し、結果を返します。 vがグループに解決された場合、グループの属性の値は再帰的に解決されません。 LogValueの呼び出し回数が閾値を超えた場合、エラーを含むValueが返されます。 Resolveの戻り値は、KindLogValuer の種類ではないことが保証されています。
func (Value) String ¶
Stringは、Valueの値を fmt.Sprint のようにフォーマットした文字列として返します。 Int64、Float64などのメソッドは、vが間違った種類の場合にpanicしますが、 Stringは決してpanicしません。
Source Files
¶
Directories
¶
Path | Synopsis |
---|---|
benchmarks
Package benchmarks contains benchmarks for slog.
|
Package benchmarks contains benchmarks for slog. |
buffer
Package buffer provides a pool-allocated byte buffer.
|
Package buffer provides a pool-allocated byte buffer. |
slogtest
Package slogtest contains support functions for testing slog.
|
Package slogtest contains support functions for testing slog. |