Skip to content

yylego/slogx

Repository files navigation

GitHub Workflow Status (branch) GoDoc Coverage Status Supported Go Versions GitHub Release Go Report Card

slogx

Enhanced slog package with invoke skip support to enable accurate source location reporting in Go logging assist functions.


CHINESE README

中文说明

Core Features

🎯 Invoke Skip Support: Provides WithCallerSkip function like zap.AddCallerSkip
📍 Accurate Source Location: Maintains correct invoke information in nested assist functions
🔗 1:1 API Support: 100% compatible with slog.Log Instance API
🍬 SugaredLogger Support: Includes zap.SugaredLogger-like flattened argument logging
Worldwide Variables: Available LOG and SUG worldwide loggers

Installation

go get github.com/yylego/slogx

Usage

Basic Usage

package main

import (
	"github.com/yylego/slogx"
)

func main() {
	// Use worldwide LOG with structured logging
	slogx.LOG.Info("application started", "version", "1.0.0", "mode", "production")

	// Use worldwide SUG with flattened arguments
	slogx.SUG.Info("client", "alice", "logged in")

	// SUG with Infoln adds spaces between arguments
	slogx.SUG.Infoln("Processing", "item", 123, "of", 456)

	// Debug level logging with structured data
	slogx.LOG.Debug("database query", "table", "clients", "duration", "45ms")

	// Warning level with flattened arguments
	slogx.SUG.Warn("high", "memory", "usage", 85, "%")
}

⬆️ Source: Source

Custom Log Instance with Invoke Skip

package main

import (
	"log/slog"
	"os"

	"github.com/yylego/slogx"
)

// logHelper demonstrates stack-frame skip in assist functions
func logHelper(instance *slogx.Logger, message string) {
	// Skip 1 frame to show logHelper invoke point instead of this function
	instance.Skip(1).Info(message, "from", "assist function")
}

// nestedLogHelper demonstrates multiple level stack-frame skip
func nestedLogHelper(instance *slogx.Logger, operation string) {
	// Skip 2 frames to show the original invoke point
	instance.Skip(2).Info("nested operation", "op", operation)
}

func main() {
	// Create custom slog log instance with JSON handler
	jsonHandler := slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
		AddSource: true,
		Level:     slog.LevelDebug,
	})
	baseLogger := slog.New(jsonHandler)

	// Wrap with slogx to enable stack-frame skip support
	instance := slogx.New(baseLogger)

	// Use in assist function with correct source location
	logHelper(instance, "message from main")

	// Direct logging without skip shows current location
	instance.Info("direct message", "level", "info")

	// Use WithCallerSkip as alternative to Skip
	instance.WithCallerSkip(1).Warn("warning from main", "skip", 1)

	// Chain with other slog methods
	instance.With("request_id", "12345").
		WithGroup("app").
		Info("chained logging", "status", "success")

	// Demonstrate nested assist with multiple skip levels
	func() {
		nestedLogHelper(instance, "cleanup")
	}()
}

⬆️ Source: Source

SugaredLogger Usage

package main

import (
	"context"
	"log/slog"
	"os"

	"github.com/yylego/slogx"
)

// processData demonstrates SugaredLogger in business logic
func processData(sugar *slogx.SugaredLogger, itemID int) {
	sugar.Info("Start", "processing", "item", itemID)
	sugar.Infoln("Completed", "item", itemID, "status", "success")
}

// contextLogger demonstrates context-aware logging
func contextLogger(sugar *slogx.SugaredLogger, ctx context.Context) {
	sugar.InfoContext(ctx, "Processing", "with", "context", "data")
	sugar.InfolnContext(ctx, "Status", "check", "complete")
}

func main() {
	// Create custom handler with text output
	textHandler := slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
		AddSource: false,
		Level:     slog.LevelInfo,
	})
	baseLogger := slog.New(textHandler)

	// Create Log Instance and convert to SugaredLogger
	instance := slogx.New(baseLogger)
	sugar := instance.Sugar()

	// Sprint-style concatenation without extra spaces
	sugar.Info("Processing", "item", 123, "of", 456)
	// Output: "Processingitem123of456"

	// Sprintln-style with spaces between each argument
	sugar.Infoln("Processing", "item", 123, "of", 456)
	// Output: "Processing item 123 of 456"

	// Warning with numeric data
	sugar.Warn("Memory", "usage", 85.5, "%", "threshold", 80)

	// Use in business logic function
	processData(sugar, 42)

	// Context-aware logging
	ctx := context.Background()
	contextLogger(sugar, ctx)

	// Create SugaredLogger from worldwide LOG
	globalSugar := slogx.LOG.Sugar()
	globalSugar.Infoln("Using", "worldwide", "LOG", "instance")

	// Combine different logging styles
	globalSugar.Info("Event", 1, "Type", "startup")
	globalSugar.Infoln("Event", 2, "Type", "ready")
}

⬆️ Source: Source

API Documentation

Core Types

Log Instance

Lightweight package around slog.LogInstance with invoke skip support:

// Create new Log Instance package
logInstance := slogx.New(slogLogger)

// Skip extra stack frames
logInstance.Skip(1).Info("message")
logInstance.WithCallerSkip(2).Warn("warning message")

// Each slog.LogInstance method supported
logInstance.Info(msg, args...)
logInstance.Debug(msg, args...)
logInstance.Warn(msg, args...)
logInstance.Warn(msg, args...)
logInstance.InfoContext(ctx, msg, args...)
logInstance.With(args...)
logInstance.WithGroup(name)

SugaredLogger

Provides flattened argument logging like zap.SugaredLogger:

// Create SugaredLogger
sugar := slogx.NewSugaredLogger(logInstance)
// And from Log Instance
sugar := logInstance.Sugar()

// Sprint-style concatenation
sugar.Info("client", 123, "action")     // "user123 action"
sugar.Debug("1", 2, 3, 4, "5", 6)     // "12 3 456"

// Sprintln-style with spaces
sugar.Infoln("client", 123, "action")   // "client 123 action"
sugar.Debugln("1", 2, 3, 4, "5", 6)   // "1 2 3 4 5 6"

// Context methods
sugar.InfoContext(ctx, args...)
sugar.InfolnContext(ctx, args...)

Worldwide Variables

// LOG - Worldwide Log Instance with structured logging
slogx.LOG.Info("message", "key", "value")

// SUG - Worldwide SugaredLog Instance with flattened arguments
slogx.SUG.Info("multiple", "arguments", 123)

// SetLog - Configure worldwide loggers with custom slog instance
customLogger := slog.New(customHandler)
slogx.SetLog(customLogger)

// NewDefault - Create Log Instance with default JSON configuration
logInstance := slogx.NewDefault()

Advanced Examples

Nested Assist Functions

func serviceMethod() {
    // Will show serviceMethod as source
    logWithContext("operation", "data")
}

func logWithContext(op string, data string) {
    // Skip 1 to show serviceMethod instead of logWithContext
    slogx.LOG.Skip(1).Info("processing", "op", op, "data", data)
}

Method Chaining

logInstance := slogx.New(slogLogger)
    .WithGroup("app")
    .With("request_id", "123")
    .Skip(1)
    
logInstance.Info("chained log instance prepared")

Custom Log Levels

ctx := context.Background()
if slogx.LOG.Enabled(ctx, slog.LevelDebug) {
    slogx.LOG.Debug("debug mode enabled")
}

📄 License

MIT License - see LICENSE.


💬 Contact & Feedback

Contributions are welcome! Report bugs, suggest features, and contribute code:

  • 🐛 Mistake reports? Open an issue on GitHub with reproduction steps
  • 💡 Fresh ideas? Create an issue to discuss
  • 📖 Documentation confusing? Report it so we can enhance it
  • 🚀 Need new features? Share the use cases to help us understand requirements
  • Performance issue? Help us optimize via reporting slow operations
  • 🔧 Configuration problem? Ask questions about complex setups
  • 📢 Track project progress? Watch the repo to get new releases and features
  • 🌟 Success stories? Share how this package enhanced the workflow
  • 💬 Feedback? We welcome suggestions and comments

🔧 Development

New code contributions, follow this process:

  1. Fork: Fork the repo on GitHub (using the webpage UI).
  2. Clone: Clone the forked project (git clone https://github.com/yourname/repo-name.git).
  3. Navigate: Navigate to the cloned project (cd repo-name)
  4. Branch: Create a feature branch (git checkout -b feature/xxx).
  5. Code: Implement the changes with comprehensive tests
  6. Testing: (Golang project) Ensure tests pass (go test ./...) and adhere to Go code style conventions
  7. Documentation: Update documentation to support client-facing changes
  8. Stage: Stage changes (git add .)
  9. Commit: Commit changes (git commit -m "Add feature xxx") ensuring backward compatible code
  10. Push: Push to the branch (git push origin feature/xxx).
  11. PR: Open a merge request on GitHub (on the GitHub webpage) with detailed description.

Please ensure tests pass and include relevant documentation updates.


🌟 Support

Welcome to contribute to this project via submitting merge requests and reporting issues.

Project Support:

  • Give GitHub stars if this project helps you
  • 🤝 Share with teammates and (golang) programming friends
  • 📝 Write tech blogs about development tools and workflows - we provide content writing support
  • 🌟 Join the ecosystem - committed to supporting open source and the (golang) development scene

Have Fun Coding with this package! 🎉🎉🎉


GitHub Stars

Stargazers

About

A structured logging extension package based on Go standard slog

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors