logx

package module
v0.0.0-...-f91144c Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 18, 2026 License: MIT Imports: 18 Imported by: 11

README

logx

A small structured logging library for Go with console, JSON, and text encoders.

Features

  • Console, JSON, and text output formats
  • Trace, debug, info, warn, error, fatal, and panic levels
  • Structured fields with primitive values, arrays, objects, errors, durations, and time values
  • Optional time, level, and caller fields
  • Runtime log level updates with AtomicLevel
  • Custom field keys, timestamp layouts, and caller formatting
  • Inherited logger fields with With, WithFields, and WithNewFields
  • Optional ANSI color output for terminal logs

Installation

go get github.com/josexy/logx

Quick Start

package main

import (
	"os"
	"time"

	"github.com/josexy/logx"
)

func main() {
	logger := logx.NewLogContext().
		WithLevel(logx.LevelTrace).
		WithLevelKey(true, logx.LevelOption{}).
		WithTimeKey(true, logx.TimeOption{Layout: time.DateTime}).
		WithWriter(logx.Lock(logx.AddSync(os.Stdout))).
		WithEncoder(logx.Console).
		Build()

	logger.Info("server started",
		logx.Int("port", 8080),
		logx.String("url", "http://localhost:8080"),
	)
}

Example console output:

2026-06-18 14:11:48	INFO	server started	{"port":8080,"url":"http://localhost:8080"}

Console Encoder

Use the console encoder for readable local development logs. It prints time, level, caller, message, and structured fields.

logger := logx.NewLogContext().
	WithLevel(logx.LevelTrace).
	WithColorfulset(true, logx.TextColorAttri{
		NumberColor: logx.CyanAttr,
	}).
	WithLevelKey(true, logx.LevelOption{}).
	WithCallerKey(true, logx.CallerOption{Formatter: logx.ShortFile}).
	WithTimeKey(true, logx.TimeOption{}).
	WithWriter(logx.Lock(logx.AddSync(logx.Output))).
	WithEncoder(logx.Console).
	WithEscapeQuote(true).
	Build()

logger.Trace("trace message", logx.String("quoted", `"value"`), logx.Int("attempt", 1))
logger.Error("error message", logx.Error("err", io.EOF))

Dynamic Level

Use AtomicLevel when you need to update the minimum log level at runtime without rebuilding existing loggers.

level := logx.NewAtomicLevel(logx.LevelWarn)

logger := logx.NewLogContext().
	WithAtomicLevel(level).
	WithLevelKey(true, logx.LevelOption{}).
	WithTimeKey(true, logx.TimeOption{}).
	WithWriter(logx.Lock(logx.AddSync(logx.Output))).
	WithEncoder(logx.Console).
	Build()

logger.Info("not printed")
logger.Warn("printed before level update")

level.SetLevel(logx.LevelDebug)
logger.Debug("printed after level update")
logger.Info("also printed after level update")

JSON Encoder

Use the JSON encoder for structured logs consumed by log collectors.

logger := logx.NewLogContext().
	WithLevel(logx.LevelTrace).
	WithLevelKey(true, logx.LevelOption{}).
	WithTimeKey(true, logx.TimeOption{Layout: time.RFC3339}).
	WithCallerKey(true, logx.CallerOption{Formatter: logx.ShortFileFunc}).
	WithWriter(logx.Lock(logx.AddSync(logx.Output))).
	WithFields(
		logx.String("service", "logx-example"),
		logx.String("env", "dev"),
	).
	WithEncoder(logx.Json).
	WithEscapeQuote(true).
	WithReflectValue(true).
	Build()

logger.Info("request handled",
	logx.Int("status", 200),
	logx.Duration("latency", 23*time.Millisecond),
	logx.Object("user",
		logx.Int("id", 10001),
		logx.String("name", "guest"),
	),
)

Example JSON output:

{"level":"INFO","time":"2026-06-18T14:11:48+08:00","service":"logx-example","env":"dev","msg":"request handled","status":200,"latency":"23ms","user":{"id":10001,"name":"guest"}}

Text Encoder

Use the text encoder for key-value logs similar to Go's slog.TextHandler.

logger := logx.NewLogContext().
	WithLevel(logx.LevelTrace).
	WithTimeKey(true, logx.TimeOption{Layout: time.RFC3339Nano}).
	WithLevelKey(true, logx.LevelOption{}).
	WithCallerKey(true, logx.CallerOption{Formatter: logx.ShortFileFunc}).
	WithWriter(logx.Lock(logx.AddSync(logx.Output))).
	WithFields(logx.String("service", "logx-example")).
	WithEncoder(logx.Text).
	Build()

logger.Info("http server started",
	logx.Bool("middleware", true),
	logx.Bool("handler", true),
	logx.Int("port", 8080),
	logx.String("url", "http://localhost:8080"),
	logx.Object("runtime",
		logx.String("os", runtime.GOOS),
		logx.String("arch", runtime.GOARCH),
	),
)

Example text output:

time=2026-06-18T14:11:48.7469115+08:00 level=INFO caller.file=example/main.go:97 caller.func=main.runTextExample msg="http server started" service=logx-example middleware=true handler=true port=8080 url=http://localhost:8080 runtime.os=windows runtime.arch=amd64

License

MIT

Documentation

Overview

reference: https://github.com/uber-go/zap/blob/master/buffer/buffer.go

Index

Constants

This section is empty.

Variables

View Source
var (
	NoColor = os.Getenv("NO_COLOR") != "" || os.Getenv("TERM") == "dumb" ||
		(!isatty.IsTerminal(os.Stdout.Fd()) && !isatty.IsCygwinTerminal(os.Stdout.Fd()))

	Output = colorable.NewColorableStdout()
)
View Source
var ConsoleEncoderSplitCharacter = byte('\t')

Functions

This section is empty.

Types

type AtomicLevel

type AtomicLevel struct {
	// contains filtered or unexported fields
}

func NewAtomicLevel

func NewAtomicLevel(level LevelType) *AtomicLevel

func (*AtomicLevel) Level

func (al *AtomicLevel) Level() LevelType

func (*AtomicLevel) SetLevel

func (al *AtomicLevel) SetLevel(level LevelType)

type Buffer

type Buffer struct {
	// contains filtered or unexported fields
}

Buffer is a thin wrapper around a byte slice. It's intended to be pooled, so the only way to construct one is via a Pool.

func NewBuffer

func NewBuffer(buf []byte) *Buffer

func (*Buffer) AppendBool

func (b *Buffer) AppendBool(v bool)

AppendBool appends a bool to the underlying buffer.

func (*Buffer) AppendByte

func (b *Buffer) AppendByte(v byte)

AppendByte writes a single byte to the Buffer.

func (*Buffer) AppendBytes

func (b *Buffer) AppendBytes(v []byte)

AppendBytes writes the given slice of bytes to the Buffer.

func (*Buffer) AppendFloat

func (b *Buffer) AppendFloat(f float64, bitSize int)

AppendFloat appends a float to the underlying buffer. It doesn't quote NaN or +/- Inf.

func (*Buffer) AppendInt

func (b *Buffer) AppendInt(i int64)

AppendInt appends an integer to the underlying buffer (assuming base 10).

func (*Buffer) AppendQuote

func (b *Buffer) AppendQuote(s string)

func (*Buffer) AppendString

func (b *Buffer) AppendString(s string)

AppendString writes a string to the Buffer.

func (*Buffer) AppendTime

func (b *Buffer) AppendTime(t time.Time, layout string)

AppendTime appends the time formatted using the specified layout.

func (*Buffer) AppendUint

func (b *Buffer) AppendUint(i uint64)

AppendUint appends an unsigned integer to the underlying buffer (assuming base 10).

func (*Buffer) Bytes

func (b *Buffer) Bytes() []byte

Bytes returns a mutable reference to the underlying byte slice.

func (*Buffer) Cap

func (b *Buffer) Cap() int

Cap returns the capacity of the underlying byte slice.

func (*Buffer) Clone

func (b *Buffer) Clone() *Buffer

func (*Buffer) Len

func (b *Buffer) Len() int

Len returns the length of the underlying byte slice.

func (*Buffer) Reset

func (b *Buffer) Reset()

Reset resets the underlying byte slice. Subsequent writes re-use the slice's backing array.

func (*Buffer) String

func (b *Buffer) String() string

func (*Buffer) TrimNewline

func (b *Buffer) TrimNewline()

TrimNewline trims any final "\n" byte from the end of the buffer.

func (*Buffer) TryGrow

func (b *Buffer) TryGrow(size int)

func (*Buffer) Write

func (b *Buffer) Write(bs []byte) (int, error)

Write implements io.Writer.

func (*Buffer) WriteByte

func (b *Buffer) WriteByte(v byte) error

WriteByte writes a single byte to the Buffer.

Error returned is always nil, function signature is compatible with bytes.Buffer and bufio.Writer

func (*Buffer) WriteString

func (b *Buffer) WriteString(s string) (int, error)

WriteString writes a string to the Buffer.

Error returned is always nil, function signature is compatible with bytes.Buffer and bufio.Writer

type CallerFormatter

type CallerFormatter uint8
const (
	// package/file:line
	ShortFile CallerFormatter = iota
	// /full/path/to/package/file:line
	FullFile
	// package/file:line package.func
	ShortFileFunc
	// /full/path/to/package/file:line package.func
	FullFileFunc
)

type CallerOption

type CallerOption struct {
	// caller key, default: "caller"
	CallerKey string
	// file key of caller, default: "file"
	FileKey string
	// function key of caller, default: "func"
	FuncKey string
	// caller formatter, default: ShortFileCaller
	Formatter CallerFormatter
	// caller skips increases the number of callers skipped by caller annotation.
	// when building wrappers around the Logger, supplying this Option prevents logx from always
	// reporting the wrapper code as the caller. default: 0
	CallerSkip int
}

type ColorAttr

type ColorAttr uint8
const (
	BlackAttr ColorAttr = iota + 30
	RedAttr
	GreenAttr
	YellowAttr
	BlueAttr
	MagentaAttr
	CyanAttr
	WhiteAttr
)
const (
	HiBlackAttr ColorAttr = iota + 90
	HiRedAttr
	HiGreenAttr
	HiYellowAttr
	HiBlueAttr
	HiMagentaAttr
	HiCyanAttr
	HiWhiteAttr
)

type ConsoleEncoder

type ConsoleEncoder struct {
	*LogContext
	// contains filtered or unexported fields
}

func (*ConsoleEncoder) Encode

func (enc *ConsoleEncoder) Encode(ent entry, fields []Field) (ret *Buffer, err error)

func (*ConsoleEncoder) Init

func (enc *ConsoleEncoder) Init()

type EncoderType

type EncoderType byte
const (
	Console EncoderType = 1 << iota
	Json
	Text
)

type Field

type Field struct {
	Key         string
	StringValue string
	AnyValue    any
	IntValue    int64
	Type        FieldType
}

func Any

func Any(key string, value any) Field

func Array

func Array(key string, value ...any) Field

func ArrayT

func ArrayT[T any](key string, value ...T) Field

func Bool

func Bool(key string, value bool) Field

func Duration

func Duration(key string, value time.Duration) Field

func Error

func Error(key string, value error) Field

func Float32

func Float32(key string, value float32) Field

func Float64

func Float64(key string, value float64) Field

func Int

func Int(key string, value int) Field

func Int8

func Int8(key string, value int8) Field

func Int16

func Int16(key string, value int16) Field

func Int32

func Int32(key string, value int32) Field

func Int64

func Int64(key string, value int64) Field

func Object

func Object(key string, value ...Field) Field

func String

func String(key string, value string) Field

func Time

func Time(key string, value time.Time) Field

func UInt

func UInt(key string, value uint) Field

func UInt8

func UInt8(key string, value uint8) Field

func UInt16

func UInt16(key string, value uint16) Field

func UInt32

func UInt32(key string, value uint32) Field

func UInt64

func UInt64(key string, value uint64) Field

type FieldType

type FieldType byte
const (
	NoneType FieldType = iota
	StringType
	BoolType
	Int8Type
	Int16Type
	Int32Type
	Int64Type
	IntType
	Uint8Type
	Uint16Type
	Uint32Type
	Uint64Type
	UintType
	Float32Type
	Float64Type
	TimeFullType
	TimeType
	DurationType
	ErrorType
	ObjectType
	ArrayType
	NilType
	AnyType
)

type JsonEncoder

type JsonEncoder struct {
	*LogContext
	// contains filtered or unexported fields
}

func (*JsonEncoder) Encode

func (enc *JsonEncoder) Encode(ent entry, fields []Field) (ret *Buffer, err error)

func (*JsonEncoder) Init

func (enc *JsonEncoder) Init()

type LevelOption

type LevelOption struct {
	// level key, default: "level"
	LevelKey string
	// lower level key
	LowerKey bool
}

type LevelType

type LevelType uint8
const (
	LevelTrace LevelType = iota
	LevelDebug
	LevelInfo
	LevelWarn
	LevelError
	LevelFatal
	LevelPanic
)

type LogContext

type LogContext struct {
	// contains filtered or unexported fields
}

func NewLogContext

func NewLogContext() *LogContext

func (*LogContext) AtomicLevel

func (lc *LogContext) AtomicLevel() *AtomicLevel

func (*LogContext) Build

func (lc *LogContext) Build() Logger

func (*LogContext) Copy

func (lc *LogContext) Copy() *LogContext

func (*LogContext) WithAtomicLevel

func (lc *LogContext) WithAtomicLevel(level *AtomicLevel) *LogContext

func (*LogContext) WithCallerKey

func (lc *LogContext) WithCallerKey(enable bool, option CallerOption) *LogContext

func (*LogContext) WithColorfulset

func (lc *LogContext) WithColorfulset(enable bool, attr TextColorAttri) *LogContext

func (*LogContext) WithEncoder

func (lc *LogContext) WithEncoder(encoder EncoderType) *LogContext

func (*LogContext) WithEscapeQuote

func (lc *LogContext) WithEscapeQuote(enable bool) *LogContext

func (*LogContext) WithFields

func (lc *LogContext) WithFields(fields ...Field) *LogContext

func (*LogContext) WithLevel

func (lc *LogContext) WithLevel(level LevelType) *LogContext

func (*LogContext) WithLevelKey

func (lc *LogContext) WithLevelKey(enable bool, option LevelOption) *LogContext

func (*LogContext) WithMsgKey

func (lc *LogContext) WithMsgKey(key string) *LogContext

func (*LogContext) WithNewFields

func (lc *LogContext) WithNewFields(fields ...Field) *LogContext

func (*LogContext) WithReflectValue

func (lc *LogContext) WithReflectValue(enable bool) *LogContext

func (*LogContext) WithTimeKey

func (lc *LogContext) WithTimeKey(enable bool, option TimeOption) *LogContext

func (*LogContext) WithWriter

func (lc *LogContext) WithWriter(writer WriteSyncer) *LogContext

type Logger

type Logger interface {
	Trace(msg string, fields ...Field)
	Debug(msg string, fields ...Field)
	Info(msg string, fields ...Field)
	Warn(msg string, fields ...Field)
	Error(msg string, fields ...Field)
	Fatal(msg string, fields ...Field)
	Panic(msg string, fields ...Field)
	Tracef(format string, args ...any)
	Debugf(format string, args ...any)
	Infof(format string, args ...any)
	Warnf(format string, args ...any)
	Errorf(format string, args ...any)
	Panicf(format string, args ...any)
	Fatalf(format string, args ...any)
	PanicWith(err error)
	ErrorWith(err error)
	FatalWith(err error)
	With(fields ...Field) Logger
}

type LoggerX

type LoggerX struct {
	// contains filtered or unexported fields
}

func (*LoggerX) Debug

func (l *LoggerX) Debug(msg string, fields ...Field)

func (*LoggerX) Debugf

func (l *LoggerX) Debugf(format string, args ...any)

func (*LoggerX) Error

func (l *LoggerX) Error(msg string, fields ...Field)

func (*LoggerX) ErrorWith

func (l *LoggerX) ErrorWith(err error)

func (*LoggerX) Errorf

func (l *LoggerX) Errorf(format string, args ...any)

func (*LoggerX) Fatal

func (l *LoggerX) Fatal(msg string, fields ...Field)

func (*LoggerX) FatalWith

func (l *LoggerX) FatalWith(err error)

func (*LoggerX) Fatalf

func (l *LoggerX) Fatalf(format string, args ...any)

func (*LoggerX) Info

func (l *LoggerX) Info(msg string, fields ...Field)

func (*LoggerX) Infof

func (l *LoggerX) Infof(format string, args ...any)

func (*LoggerX) Panic

func (l *LoggerX) Panic(msg string, fields ...Field)

func (*LoggerX) PanicWith

func (l *LoggerX) PanicWith(err error)

func (*LoggerX) Panicf

func (l *LoggerX) Panicf(format string, args ...any)

func (*LoggerX) Trace

func (l *LoggerX) Trace(msg string, fields ...Field)

func (*LoggerX) Tracef

func (l *LoggerX) Tracef(format string, args ...any)

func (*LoggerX) Warn

func (l *LoggerX) Warn(msg string, fields ...Field)

func (*LoggerX) Warnf

func (l *LoggerX) Warnf(format string, args ...any)

func (*LoggerX) With

func (l *LoggerX) With(fields ...Field) Logger

type TextColorAttri

type TextColorAttri struct {
	KeyColor     ColorAttr
	StringColor  ColorAttr
	BooleanColor ColorAttr
	FloatColor   ColorAttr
	NumberColor  ColorAttr
}

type TextEncoder

type TextEncoder struct {
	*LogContext
	// contains filtered or unexported fields
}

func (*TextEncoder) Encode

func (enc *TextEncoder) Encode(ent entry, fields []Field) (ret *Buffer, err error)

func (*TextEncoder) Init

func (enc *TextEncoder) Init()

type TimeOption

type TimeOption struct {
	// time key, default: time
	TimeKey string
	// convert time to int64 timestamp with UnixNano, default: false
	Timestamp bool
	// time layout, default: time.DateTime
	Layout string
}

type WriteSyncer

type WriteSyncer interface {
	io.Writer
	Sync() error
}

func AddSync

func AddSync(w io.Writer) WriteSyncer

func Lock

func Lock(ws WriteSyncer) WriteSyncer

Lock wraps a WriteSyncer in a mutex to make it safe for concurrent use. In particular, *os.Files must be locked before use. See zap log

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL