Documentation
¶
Overview ¶
Package log is tt's logging facade over log/slog.
Diagnostics - progress, warnings, errors, debug detail - go to stderr through slog. A command's result never goes through this package; it goes to stdout through github.com/tarantool/tt/sdk/output.
The tt core owns the process logger: it installs the handler that renders records as text or JSON, filters by level and redacts secrets, and makes it slog.Default. Nothing here configures handlers. A module logs through the *slog.Logger tt hands it; the printf functions below serve tt's own code.
The levels are slog's four: Debug, Info, Warn, Error. There is no Fatal: a failure is returned as an error and the core decides the exit code.
The package also holds the secret-redaction logic (Redactor, Secret, RedactURL) so that the core's handler and the tests of any module apply the same rules.
Index ¶
- Constants
- func Debug(msg string, attrs ...any)
- func Debugf(format string, args ...any)
- func Error(msg string, attrs ...any)
- func Errorf(format string, args ...any)
- func Info(msg string, attrs ...any)
- func Infof(format string, args ...any)
- func Library(name string) *slog.Logger
- func LibraryOf(base *slog.Logger, name string) *slog.Logger
- func Logger() *slog.Logger
- func Redact(text string) string
- func RedactTarget(target string) string
- func RedactURL(raw string) string
- func RegisterSecret(value string) bool
- func Spinner(msg string) func()
- func SpinnerOf(logger *slog.Logger, msg string) func()
- func Warn(msg string, attrs ...any)
- func Warnf(format string, args ...any)
- type Redactor
- type Secret
- type StatusHandler
Constants ¶
const LibraryKey = "library"
LibraryKey is the attribute key that names the library a record came from.
const MinSecretLen = 4
MinSecretLen is the shortest value a Redactor accepts. Redaction replaces every occurrence of a value anywhere in a message, so a short value masks ordinary text: a one-letter "secret" would mask that letter everywhere, and a three-letter one matches common words and path parts. Four characters is the shortest a real password or token plausibly is while still rare in prose. URI userinfo is masked by shape regardless of its length.
const Redacted = "[REDACTED]"
Redacted is what a secret is replaced with.
Variables ¶
This section is empty.
Functions ¶
func Debug ¶
Debug logs msg at Debug level on the process logger. The optional attrs are key-value pairs or slog.Attr values, as for slog.Logger.Debug.
func Error ¶
Error logs msg at Error level on the process logger. The optional attrs are key-value pairs or slog.Attr values, as for slog.Logger.Error.
func Info ¶
Info logs msg at Info level on the process logger. The optional attrs are key-value pairs or slog.Attr values, as for slog.Logger.Info.
func Library ¶
Library returns a logger for a third-party library, built on the process logger. See LibraryOf.
It binds the handler slog.Default has at the time of the call, so call it where the library is set up, not in a package-level variable initialised before tt has configured logging.
func LibraryOf ¶
LibraryOf returns a logger for a third-party library, built on base.
A library's Info is chatter from tt's point of view - go-luarocks logs every line luarocks prints at Info - so records from Info up to, but not including, Warn are demoted by the distance between Info and Debug. Warn and Error pass unchanged: those are for the user.
Every record carries a top-level library=<name> attribute. It is a plain attribute rather than a group so that the library's own attributes keep their keys and the text format stays one flat line.
func RedactTarget ¶
RedactTarget returns target, a connection URI or whatever a user typed in the place of one, fit to be shown in an error or a log message: the credentials of a URI are hidden whether or not it parses (connect.RedactCredentials), and so is every secret registered with the process (Redact).
Unlike RedactURL it does not need the string to be a URL, nor the userinfo to be well formed: a message that quotes a piece of a target cut at a ":", such as the "instance" of user:password@host:3301, or a target with a "/" in its password, passes through here.
func RedactURL ¶
RedactURL returns raw with its userinfo removed entirely and the remainder redacted with the process-wide registry.
url.URL.Redacted is not enough: it masks only a password and keeps a bare username, and in https://<token>@host the username is the secret. A raw string that does not parse as a URL with userinfo - a Tarantool admin:secret@host:3301 parses as an opaque one - is redacted by Redact.
func RegisterSecret ¶
RegisterSecret adds value to the process-wide registry so that it is masked in every log record from then on. It reports whether the value was accepted: values shorter than MinSecretLen are ignored.
func Spinner ¶
func Spinner(msg string) func()
Spinner shows msg with an animation on the status line of the process logger until the returned stop function is called. See SpinnerOf.
func SpinnerOf ¶
SpinnerOf shows msg with an animation on the status line of logger's handler until the returned stop function is called.
The spinner is progress for a person watching a terminal: when the handler is not a StatusHandler - the output is not a terminal, the format is JSON, or the logger is not tt's - nothing is shown and stop does nothing. It never writes to stdout. Records logged while it spins stay whole.
Types ¶
type Redactor ¶
type Redactor struct {
// contains filtered or unexported fields
}
Redactor masks secrets in log text: every value registered with it, and the userinfo of anything that looks like a URI. It is safe for concurrent use. The process has one, reached through Secrets; tests can make their own with NewRedactor.
func NewRedactor ¶
func NewRedactor() *Redactor
NewRedactor returns a Redactor with no registered values. It still masks URI userinfo.
func Secrets ¶
func Secrets() *Redactor
Secrets returns the process-wide Redactor that RegisterSecret adds to and the core's log handler applies.
func (*Redactor) Redact ¶
Redact returns text with every registered value and every URI userinfo replaced by Redacted. A URI with a scheme loses its whole userinfo, since a bare "token@" is as much a secret as "user:password@"; without a scheme only the "user:password@" form is recognised.
func (*Redactor) RedactAttr ¶
RedactAttr returns attr with its secrets masked. The value is resolved first, so a slog.LogValuer is redacted by what it logs as. Strings are redacted, groups member by member at any depth, and any other value - an error, a struct - by its fmt "%+v" rendering: when that rendering holds a secret the value is replaced by the redacted text, otherwise it is kept as it is. Numbers, booleans, times and durations pass through.
func (*Redactor) RedactRecord ¶
RedactRecord returns a copy of record with its message and attributes redacted. Attributes a handler holds from WithAttrs are not part of the record; the handler redacts those itself.
type Secret ¶
type Secret struct {
// contains filtered or unexported fields
}
Secret holds a value that must never reach a log or an output: its fmt rendering under every verb, its slog value and its text and JSON encodings are all Redacted. Only Secret.Reveal returns the value.
A Secret does not register its value; call RegisterSecret as well when the value may also leak through a path that does not hold the Secret, such as a URL or an error message.
func (Secret) Format ¶
Format writes Redacted for every fmt verb. Without it, verbs a Stringer does not cover, such as %d, would print the struct and its field.
func (Secret) MarshalText ¶
MarshalText returns Redacted; encoding/json and YAML encoders use it.
type StatusHandler ¶
type StatusHandler interface {
slog.Handler
// Status shows msg on the status line until the returned stop is
// called. Stop clears the line, waits until nothing more is drawn and
// may be called more than once. A handler that cannot show a status
// line at the moment returns a stop that does nothing.
Status(msg string) (stop func())
}
StatusHandler is implemented by a handler that can keep a transient status line - a spinner - on its output while a long operation runs. The core's text handler implements it when stderr is a terminal; it keeps the status line below the records it writes, clearing the line before a record and drawing it again after.