fdn
API
fdn
packageAPI reference for the fdn
package.
Imports
(8)
F
function
TestNewStructured_EmitsOneJSONObjectPerLine
Parameters
t
pkg/log/fdn/fdn_test.go:13-34
func TestNewStructured_EmitsOneJSONObjectPerLine(t *testing.T)
{
var buf bytes.Buffer
l := NewStructured(&buf)
l.Info("started")
l.Error("failed")
lines := strings.Split(strings.TrimSpace(buf.String()), "\n")
if len(lines) != 2 {
t.Fatalf("expected 2 lines, got %d: %q", len(lines), buf.String())
}
for _, line := range lines {
var entry map[string]any
if err := json.Unmarshal([]byte(line), &entry); err != nil {
t.Fatalf("line is not JSON: %q (%v)", line, err)
}
if entry["msg"] == nil {
t.Errorf("entry has no message: %q", line)
}
}
}
F
function
TestNewStructured_KeepsTheSuccessSeverity
Parameters
t
pkg/log/fdn/fdn_test.go:36-52
func TestNewStructured_KeepsTheSuccessSeverity(t *testing.T)
{
var buf bytes.Buffer
NewStructured(&buf).Success("done")
var entry map[string]any
if err := json.Unmarshal([]byte(strings.TrimSpace(buf.String())), &entry); err != nil {
t.Fatalf("not JSON: %q (%v)", buf.String(), err)
}
fields, ok := entry["fields"].(map[string]any)
if !ok {
t.Fatalf("entry carries no fields: %q", buf.String())
}
if fields["status"] != "success" {
t.Errorf("success severity lost, fields were %v", fields)
}
}
F
function
TestWrap_RoundTrips
Parameters
t
pkg/log/fdn/fdn_test.go:54-75
func TestWrap_RoundTrips(t *testing.T)
{
var buf bytes.Buffer
inner := flogger.New(
flogger.WithoutDefaultSink(),
flogger.WithSink(flogger.NewConsoleSink(&buf)),
)
wrapped := Wrap(inner)
wrapped.Info("hello")
if !strings.Contains(buf.String(), "hello") {
t.Errorf("message did not reach the wrapped logger, got %q", buf.String())
}
back, ok := Unwrap(wrapped)
if !ok {
t.Fatal("Unwrap failed on a logger this package produced")
}
if back != inner {
t.Error("Unwrap returned a different logger")
}
}
F
function
TestWrap_NilFallsBackToConsole
Parameters
t
pkg/log/fdn/fdn_test.go:77-81
func TestWrap_NilFallsBackToConsole(t *testing.T)
{
if Wrap(nil) == nil {
t.Error("Wrap(nil) must return a usable logger")
}
}
S
struct
wrapped
wrapped adapts a Foundation logger to the CLI logging contract.
pkg/log/fdn/fdn.go:24-26
type wrapped struct
Methods
Info
Method
Parameters
format
string
a
...any
func (*wrapped) Info(format string, a ...any)
{
l.inner.Info(render(format, a...), status(log.LogLevelInfo))
}
Success
Method
Parameters
format
string
a
...any
func (*wrapped) Success(format string, a ...any)
{
l.inner.Info(render(format, a...), status(log.LogLevelSuccess))
}
Warning
Method
Parameters
format
string
a
...any
func (*wrapped) Warning(format string, a ...any)
{
l.inner.Warn(render(format, a...), status(log.LogLevelWarning))
}
Error
Method
Parameters
format
string
a
...any
func (*wrapped) Error(format string, a ...any)
{
l.inner.Error(render(format, a...), status(log.LogLevelError))
}
Fields
| Name | Type | Description |
|---|---|---|
| inner | flogger.Logger |
F
function
Wrap
Wrap adapts an existing Foundation logger so it can be handed to
cli.WithLogger. Sinks, level and bound fields of the wrapped logger are kept.
Parameters
inner
Returns
pkg/log/fdn/fdn.go:35-40
func Wrap(inner flogger.Logger) log.Logger
{
if inner == nil {
return log.New()
}
return &wrapped{inner: inner}
}
Example
fl := logger.New(logger.WithLevel(logger.DebugLevel))
cli.Run(app, cli.WithLogger(fdn.Wrap(fl)))
F
function
NewStructured
NewStructured returns a logger that emits one JSON object per line on w,
suitable for a service, a CI job, or anything that reads logs with a parser
rather than with eyes.
Parameters
Returns
pkg/log/fdn/fdn.go:49-55
func NewStructured(w io.Writer) log.Logger
{
inner := flogger.New(
flogger.WithoutDefaultSink(),
flogger.WithSink(flogger.NewConsoleSink(w)),
)
return &wrapped{inner: inner}
}
Example
cli.Run(app, cli.WithLogger(fdn.NewStructured(os.Stdout)))
F
function
Unwrap
Unwrap returns the Foundation logger behind l, and false when l was not
produced by this package. Use it to add a sink or to shut the logger down.
Parameters
Returns
bool
pkg/log/fdn/fdn.go:59-65
func Unwrap(l log.Logger) (flogger.Logger, bool)
{
w, ok := l.(*wrapped)
if !ok {
return nil, false
}
return w.inner, true
}
F
function
render
render formats the message only when arguments were supplied, so that a
message containing a percent sign survives being logged on its own.
Parameters
format
string
a
...any
Returns
string
pkg/log/fdn/fdn.go:85-90
func render(format string, a ...any) string
{
if len(a) == 0 {
return format
}
return fmt.Sprintf(format, a...)
}
F
function
status
Parameters
level
Returns
pkg/log/fdn/fdn.go:92-94
func status(level log.LogLevel) flogger.Field
{
return flogger.Field{Key: statusField, Value: level.String()}
}