logx

package
v0.0.1 Latest Latest
Warning

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

Go to latest
Published: Aug 17, 2025 License: Apache-2.0 Imports: 9 Imported by: 39

README

Intro

This package defines library to manage Logging. The purpose of logging is

  • to record events (aka. logs) that occur in a software system
  • essential for:
    • Debugging: Identifying the root cause of issues.
    • Monitoring: Tracking application health, performance, and usage.
    • Auditing: Providing a record of significant actions for security or compliance purposes.

Logs are often categorized by severity levels, such as DEBUG, INFO, WARN, and ERROR, to help developers filter and prioritize information and so action.

The code

interface.go

Defines the logging methods used by the GALI (Global Application Logger Instance)

loggerXXX.go

Defines an implementation for a specific driver. e.g.

  • loggerZap.go for the Uber's zap driver
  • loggerStd.go for the Go standard logging driver

loggerXXXConfig.go

configure a specific driver for all available app env. e.g.

  • loggerZapConfig.go configure the driver to display differently in dev and prod

How it works

require the module in the go.mod of your project

require github.com/abtransitionit/gocore v1.0.0

import the package in the project's main.go

import "github.com/abtransitionit/gocore/logx

Use the logger in the code

logx.Info(...)

See it in action

In Development mode

// use GO std logger driver, no matter the env
go run main.go ...

// use Zap logger driver
APP_LOG_DRIVER=zap go run main.go ...

In Production mode

// use GO std logger driver, no matter the env
go run main.go ...

// use Zap logger driver with a prod configuration 
APP_LOG_DRIVER=zap APP_ENV=prod go run main.go ...

// use Zap logger driver with a dev configuration 
APP_LOG_DRIVER=zap APP_ENV=dev go run main.go ..

configuring the Zap logger driver

The code provide a simple configuration for 2 environments named dev and prod

zap dev Vs. zap prod

Feature zap.NewDevelopment() zap.NewProduction()
Log Format Human-readable console output. Structured, machine-readable JSON output.
Performance Slower due to extra formatting for human-readability. Optimized for speed with zero-allocation logging.
Log Level By default, logs at the DEBUG level and above. By default, logs at the INFO level and above.
Caller Info Includes file and line number by default. Includes file and line number by default.
Stack Traces Prints stack traces on DPanic and Panic levels. Prints stack traces on ERROR and FATAL levels.

Example

Log Format:

  • dev:
INFO	logx/loggerZap.go:40	Test some code.
  • prod:
{"level":"info","ts":1755256591.774873,"caller":"logx/loggerZap.go:40","msg":"Test some code."}

Todo

Add more useful methods to interface

  • add more methods to the interface to be ilmplemented. example:
logx.Infof("installing %s", cliConf.Name)
logx.Errorf("Error: %v", err)

Integrate package errox to logx

A logger should be smart enough to detect and handle custom errors, automatically including the stack trace when it's available.

Let's move on to the next major step: integrating your new errorx package with your logx package. This is where the true power of your production-grade design will be realized. Your logger should be smart enough to detect and handle your custom errors, automatically including the stack trace when it's available.


Step 1: Define a Logging Function for Errors

First, we need to add a new function to your logx interface and concrete implementations. This function, let's call it LogErr, will be specifically designed to handle errors. It will check if the error implements the errorx.Stacker interface and, if so, log the stack trace along with the error message.

a. Update interface.go

Add the LogErr method to your Logger interface.

// interface.go
package logx

type Logger interface {
	Info(format string, v ...any)
	Error(format string, v ...any)
	// LogErr logs an error, including a stack trace if available.
	LogErr(err error, format string, v ...any)
}

This ensures that every logger implementation you create (e.g., stdLogger, zapLogger) must handle errors in this new, standardized way.


Step 2: Implement LogErr in Your Loggers

Now, you need to add the implementation of LogErr to your stdLogger and zapLogger types. This is where you'll use the errorx utilities we just created.

a. stdlogger.go

Modify stdlogger.go to use the errorx.FormatStack function to print the stack trace.

// stdlogger.go
package logx

import (
	"log"
	"os"
	"strings"

	"github.com/abtransitionit/gocore/errorx"
)

// NewStdLogger returns a new Logger instance based on the provided configuration.
func NewStdLogger(config StdLoggerConfig) Logger {
	return &stdLogger{
		logger: log.New(config.Out, config.Prefix, config.Flag),
	}
}

func (s *stdLogger) Info(format string, v ...any) {
	s.logger.Printf("INFO: "+format, v...)
}

func (s *stdLogger) Error(format string, v ...any) {
	s.logger.Printf("ERROR: "+format, v...)
}

// LogErr logs an error message and its stack trace if it exists.
func (s *stdLogger) LogErr(err error, format string, v ...any) {
	var sb strings.Builder
	sb.WriteString("ERROR: ")
	sb.WriteString(fmt.Sprintf(format, v...))
	sb.WriteString(": ")
	sb.WriteString(err.Error())
	sb.WriteString("\n")

	if stack := errorx.GetStack(err); stack != nil {
		sb.WriteString(errorx.FormatStack(stack))
	}

	s.logger.Println(sb.String())
}
b. zaplogger.go

Modify zaplogger.go to leverage zap's structured logging capabilities. Instead of a long string, you'll log the stack trace as a dedicated field.

// zaplogger.go
package logx

import (
	"fmt"
	"go.uber.org/zap"
	"github.com/abtransitionit/gocore/errorx"
)

// NewZapLogger returns a new Logger instance based on a custom zap.Config.
func NewZapLogger(config zap.Config) Logger {
	l, _ := config.Build()
	return &zapLogger{
		logger: l,
	}
}

// Info logs a message with the zap logger at Info level.
func (z *zapLogger) Info(format string, v ...any) {
	z.logger.Info(fmt.Sprintf(format, v...))
}

// Error logs a message with the zap logger at Error level.
func (z *zapLogger) Error(format string, v ...any) {
	z.logger.Error(fmt.Sprintf(format, v...))
}

// LogErr logs an error message with the zap logger, including the stack trace as a structured field.
func (z *zapLogger) LogErr(err error, format string, v ...any) {
	fields := []zap.Field{
		zap.Error(err),
		zap.String("message", fmt.Sprintf(format, v...)),
	}

	if stack := errorx.GetStack(err); stack != nil {
		fields = append(fields, zap.String("stack_trace", errorx.FormatStack(stack)))
	}

	z.logger.Error(err.Error(), fields...)
}

Step 3: Use the New Logging Function

Now, any part of your application that needs to log an error can use the new logx.LogErr function. For example, your gotest application could now handle errors like this:

// main.go (simplified example)
package main

import (
	"github.com/abtransitionit/gocore/errorx"
	"github.com/abtransitionit/gocore/logx"
)

func main() {
	logx.Init() // Initializes logger based on env vars

	err := someFunctionThatReturnsAnError()
	if err != nil {
		// The logger automatically checks for a stack trace.
		logx.LogErr(err, "An error occurred while running the task")
	}
}

func someFunctionThatReturnsAnError() error {
	// Create a new error with a stack trace.
	return errorx.New("failed to connect to the database")
}

This final step creates a powerful, unified logging and error management system. Your applications will now generate rich, debuggable log messages in development and clean, structured ones in production, all with a consistent and easy-to-use API.

Documentation

Overview

Copyright © 2025 AB TRANSITION IT abtransitionit@hotmail.com

This file defines the interface any logger driver must implements.

stdloggerconfig.go

config.go

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Error

func Error(format string, v ...any)

Name: Error Description: a convenience function that delegates to the global logger's Error method. Notes: - a convenience for the function of the same name in the interface

func ErrorWithNoStack

func ErrorWithNoStack(err error, format string, v ...any)

Name: ErrorWithNoStack Description: is a convenience function that delegates to the global logger's ErrorWithNoStack method. Notes: - a convenience for the function of the same name in the interface

func ErrorWithStack

func ErrorWithStack(err error, format string, v ...any)

Name: ErrorWithStack Description: is a convenience function that delegates to the global logger's ErrorWithStack method. Notes: - a convenience for the function of the same name in the interface

func Info

func Info(format string, v ...any)

Name: Info Description: a convenience function that delegates to the global logger's Info method. Notes: - a convenience for the function of the same name in the interface

func Init

func Init()

Name: Init Description: initializes the GALI Notes: The logger is choosen based on the following environment variables - APP_LOG_DRIVER : to choose the logger driver - APP_ENV : to choose the logger driver format

func NewDevConfig

func NewDevConfig() zap.Config

Name: NewDevConfig Return: - zap.Config: a configuration instance for the development environment. Notes: - It includes customizations like colorized levels and short caller paths.

func NewProdConfig

func NewProdConfig() zap.Config

Name: NewProdConfig Return: - zap.Config: a configuration instance for the production environment. Notes: - This is standard the default zap production config.

Types

type Logger

type Logger interface {
	Info(format string, v ...any)
	Error(format string, v ...any)
	//logs an error, including a stack trace if one is available.
	ErrorWithStack(err error, format string, v ...any)
	// logs an error without including a stack trace.
	ErrorWithNoStack(err error, format string, v ...any)
}

Name: Logger Description: defines the logging methods used in the application that all loggers must implements. Notes: - This allows for easy swapping of the underlying logging implementation.

var GlobalLogger Logger

Name: GlobalLogger Description: the main logging instance for the application, Notes: - reference the GALI (Global Application Logger Instance) of type Logger (the interface)

func NewStdLogger

func NewStdLogger(config StdLoggerConfig) Logger

Name: NewStdLogger Description: creates a new stdLogger instance. Returns: - Logger: an instance to the stdLogger that satisfies the Logger using the provided configuration.

func NewZapLogger

func NewZapLogger(config zap.Config) Logger

Name: NewZapLogger Description: creates a new zapLogger instance for any environment (production or development). Return: - Logger: an instance to the zapLogger configured for an env (dev, prod, ..) and that satisfies the Logger interface.

type StdLoggerConfig

type StdLoggerConfig struct {
	Out    io.Writer
	Prefix string
	Flag   int
}

Name: StdLoggerConfig Description: holds the configuration for GO standard logger driver.

func NewStdDevConfig

func NewStdDevConfig() StdLoggerConfig

Name: NewStdDevConfig Description: creates a development configuration for GO standard logger driver.

func NewStdProdConfig

func NewStdProdConfig() StdLoggerConfig

Name: NewStdProdConfig Description: creates a production configuration for GO standard logger driver.

Jump to

Keyboard shortcuts

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