logger

package module
v0.1.4 Latest Latest
Warning

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

Go to latest
Published: Nov 29, 2024 License: MIT Imports: 15 Imported by: 0

README

Logger - A Lightweight Logging System with Advanced Features

Logger is a Go package that provides a versatile and efficient logging system designed for applications that require structured log management. With its built-in SQLite integration, filtering capabilities, customizable terminal output, and alert notifications, Logger offers a comprehensive solution for tracking and managing application events.

Features

SQLite-Based Logging

Logs are stored in a lightweight SQLite database, ensuring persistence and easy retrieval without relying on external systems.

Flexible Filtering and Configurable Terminal Output

Quickly filter logs by various criteria (e.g., log levels, timestamps, tags) and print them directly to the terminal for debugging or analysis. Using the powerful charmbracelet/lipgloss package, Logger provides styled terminal output with predefined, visually appealing formats. You can customize the visibility and detail level of key log components, such as:

  • Caller Information: Choose whether to display or hide details like file names, line numbers, and function names.
  • Timestamps: Include or exclude timestamps or adjust their level of precision.
  • Tags: Display all tags or omit them entirely for cleaner output.

Logs can be printed in two distinct formats:

  • Inline Mode: Logs are printed as compact, single-line entries for efficient viewing of multiple logs at once.
  • Block Mode: Each log is displayed as a "card," with detailed, structured output that visually separates it from other logs for enhanced readability.

This flexible configuration ensures that the log output is tailored to the specific needs of the user, whether they require concise summaries or detailed insights.

Export Logs to Multiple Formats

Easily export log data from the SQLite database in various formats:

  • JSON: Structured and machine-readable for integration with other tools.
  • CSV: Convenient for data analysis and spreadsheet manipulation.
  • LOG: Traditional plain text format for compatibility with other log systems.
Alert Log System

Create "alert logs" that trigger real-time notifications for critical events, allowing immediate response to important issues. Alerts are powered by the gen2brain/beeep package, which provides cross-platform notifications via native system alerts, ensuring you never miss a critical event.

Why Choose Logger?

Logger combines simplicity with powerful features, making it ideal for developers who want a self-contained logging solution that goes beyond traditional file-based logging. Whether you need detailed logs for debugging, instant alerts for critical events, or stylish terminal output, Logger has you covered. With Logger, you get a complete, lightweight logging solution that is visually engaging and ready to meet your application's logging needs.


Usage

Install the Package

Get the logger package via go get:

go get github.com/Tagliapietra96/logger
Basic Usage

Create and configure a basic logger:

package main

import "github.com/Tagliapietra96/logger"

func main() {
    // Initialize a logger with the default configuration
    log := logger.New() 

    // Initialize a logger with default tags 'tag1' and 'tag2'
    // All logs created with this logger will include these tags
    logWithTags := logger.New("tag1", "tag2") 
}
Advanced Configuration

Logger provides several options to customize how logs are stored, formatted, and displayed. Below are detailed configurations to tailor the logger to your needs.

Setting the Log Storage Folder

By default, the logs are stored in an SQLite database in the current working directory. You can change the storage location with the Folder method:

log := logger.New()

// Set the folder where the SQLite database will be stored
log.Folder("~/projects/my-logs/")

Note: Ensure the specified folder exists and has the necessary write permissions.

Configuring Log Output Format (Inline vs Block)

You can control how logs are printed to the terminal. Logs can be displayed in a compact, single-line format (inline), or in a more detailed, block format, where each log is presented as a card-like entry (block).

// Print logs in a single-line format
log.Inline(true)  

// Print logs in a block format (default)
log.Inline(false)  

Inline Mode: Suitable for quick, concise debugging. Block Mode: Ideal for comprehensive, formatted log displays with better readability.

Customizing Caller Information Display

Control how much information about the function calling the logger is shown. You can hide it completely, or display varying levels of detail:

// Hide all caller information
log.Caller(logger.HideCaller)

// Show only the caller's file name (default behavior)
log.Caller(logger.ShowCallerFile)

// Show the file name and the line number where the log was called
log.Caller(logger.ShowCallerLine)

// Show file name, line number, and function name for precise tracking
log.Caller(logger.ShowCallerFunction)

Use Case: Showing the caller details is useful for debugging complex applications where knowing the exact source of a log is critical.

Configuring Timestamp Display

Decide how much timestamp information you want in your logs. You can hide it entirely or choose from different levels of detail:

// Hide timestamp information entirely
log.Timestamp(logger.HideTimestamp)

// Display only the date in the format "YYYY-MM-DD"
log.Timestamp(logger.ShowDate)  

// Display date and time in the format "YYYY-MM-DD HH:MM:SS" (default)
log.Timestamp(logger.ShowDateTime)

// Display the full timestamp with the day of the week included
log.Timestamp(logger.ShowFullTimestamp)
  • Default Format: 2006-01-02 15:04:05
  • Full Timestamp Example: Monday 2006-01-02 15:04:05
Managing Tags for Logs

Tags help categorize logs, making it easier to filter and search. You can add or remove tags dynamically.

// Add tags to the logger instance
log.Tags("tag1", "tag2")

// Add another tag to the existing list
log.Tags("tag3")  // Now the tags are: []string{"tag1", "tag2", "tag3"}

// Override existing tags with a new set
log.SetTags("new-tag1", "new-tag2")  

// Clear all tags
log.SetTags()  // Now the logger has no tags
Configuring Fatal Notifications

Customize the message and title for critical errors using the SetFatal method. This is particularly useful for displaying user-friendly or context-specific messages.

// Set a custom title and message for fatal error notifications
log.SetFatal("MyApp - CRITICAL ERROR", "Oops! Something went wrong. Check the logs.")
  • Default Title: "Fatal"
  • Default Message: "An error occurred, please check the logs for more information"

These configurations allow you to fully customize your logging setup, ensuring that the logs are both informative and easy to manage, while maintaining flexibility in how they are displayed and stored.

Creating a Copy of the Logger Configuration

Logger allows you to create an exact copy of the current logger instance using the Copy method. This is useful when you want to reuse the same logging configuration but apply it with different tags or additional settings without modifying the original logger.

log := logger.New()

// Customize the original logger configuration
log.Folder("~/projects/my-logs/")
log.Tags("initial", "setup")
log.Caller(logger.ShowCallerFile)

// Create a copy of the existing logger
log2 := log.Copy()

// Modify the copied logger independently
log2.Tags("new-tag") // Now log2 has ["initial", "setup", "new-tag"]
log2.Caller(logger.HideCaller) // Different caller visibility from original
Use Cases:
  • Independent Logging for Different Contexts: Use the same core configuration but apply different tags for logging in different parts of your application (e.g., "auth", "database").
  • Debugging Different Modules Separately: Keep the original logger for general application logs and use the copied instance to focus on specific modules without altering the primary configuration.
  • Isolated Fatal Handling: Customize fatal notifications independently for various modules while retaining a shared base configuration.

The Copy feature enhances flexibility by enabling modular and context-aware logging configurations while maintaining a consistent base setup across different components of your application.

Log Management Functionality

Logger provides three primary ways to manage logs: saving them to the SQLite database, printing them directly to the console without persistence, and retrieving and printing existing logs from the database. This section details these functionalities, offering examples and explanations for each.

Saving Logs to the Database

Logs can be saved to the database using various log levels such as Debug, Info, Warn, Error, and Fatal. Each method formats the provided message and stores it in the SQLite database with optional tags and metadata. The Fatal log type also triggers an alert and exits the program.

Example Usage:
package main
import (
    "github.com/Tagliapietra96/logger"
    
    "time"
)
func main() {
    log := logger.New()
    msg := "initializing components"
    // Create different log types and save them to the database
    log.Debug("Debug message: %s", msg)
    log.Info("App started at: %s", time.Now().Format("2006-01-02 15:04:05"))
    log.Error("oh no! an error")
    err := myFunc()
    if err != nil {
        // Fatal log - triggers alert and exits
        log.Fatal(err)
    }
    err := log.Warn("Potential issue detected: low disk space")
    if err != nil {
        panic(err)
    }
}
Key Details:
  • Formatting: Uses fmt.Sprintf for message formatting.
  • Persistence: Logs are stored in the SQLite database.
  • Error Handling: Each method returns an error if log creation fails.
  • Alerts: Fatal logs trigger alerts using the beeep package and terminate the application.
Use Cases:
  • Tracking critical system events with persistent logs.
  • Debugging issues by storing logs for later retrieval and analysis.
  • Immediate notification of unrecoverable errors.
Printing Logs Directly to the Console (Without Persistence)

For real-time feedback, logs can be printed directly to the terminal using PrintDebug, PrintInfo, PrintWarn, PrintError, and PrintFatal. These logs are not saved in the database.

Example Usage:
package main

import (
    "github.com/Tagliapietra96/logger"
    
    "fmt"
)

func main() {
    log := logger.New()

    // Print logs directly without saving them to the database
    log.PrintDebug("Debugging: %s", "initializing cache")
    log.PrintInfo("Starting process: %s", "data sync")
    log.PrintWarn("Warning: %s", "deprecated API usage")
    
    err := fmt.Errorf("network timeout")
    log.PrintError("Error: %v", err)
    
    // Print fatal log and exit
    log.PrintFatal(fmt.Errorf("Fatal error: %s", "database connection lost"))
}
Key Details:
  • Real-Time Output: Logs are printed directly to the terminal.
  • No Persistence: These logs are not stored in the database.
  • Exit on Fatal: PrintFatal logs terminate the program after printing.
Use Cases:
  • Debugging in development environments where persistence is unnecessary.
  • Immediate visibility for application events during runtime.
  • Custom error reporting without cluttering the database.
Printing Logs from the Database

Logs stored in the database can be queried and printed using PrintLogs. This method supports query options to filter logs based on criteria like level, tags, or date range.

Example Usage:
package main

import (
	"github.com/Tagliapietra96/logger"
	"github.com/Tagliapietra96/logger/queries"
)

func main() {
    log := logger.New()

    // Print all logs stored in the database
    log.PrintLogs()

    // Print only "Error" level logs
    log.PrintLogs(queries.LevelEqual(logger.Error))

    // Print only 10 logs
    log.PrintLogs(queries.AddLimit(10))

    // Print the last 10 logs with "Error" level
    log.PrintLogs(
        queries.LevelEqual(logger.Error),
        queries.AddLimit(10),
        queries.SortTimestamp("desc")
    )
}
Key Details
  • Flexible Querying: Use QueryOption to filter logs by level, tags, or date range. The package also includes the sub-package github.com/Tagliapietra96/logger/queries, which provides a comprehensive list of ready-to-use QueryOption instances that cover most common use cases, simplifying complex query creation.
  • Database Retrieval: Retrieves logs from SQLite and prints them in the configured format, ensuring consistency between stored and displayed data.
  • Inline or Block Output: Logs can be printed inline (single-line log entries) or in block format (each log displayed as a separate card-like structure), allowing for flexible presentation.
Use Cases
  • Postmortem Analysis: Retrieve logs after a critical failure to perform in-depth analysis and identify root causes. The queries sub-package can streamline complex queries for these scenarios.
  • Selective Viewing: View logs filtered by level, tags, or other criteria for efficient debugging and issue tracking. Use predefined QueryOption from the queries sub-package to expedite setup.
  • Audit Trail Creation: Query logs from specific date ranges to create detailed audit trails. The queries package provides options to filter by time windows or log levels for compliance and reporting.

Export Functionality

The Export method in the logger package provides a powerful way to export logs from the SQLite database to different file formats. This feature supports exporting logs based on specified query options, offering flexibility for different use cases such as data analysis, archival, or reporting.

Key Features
Export Formats:

The ExportType parameter allows exporting logs in one of the following formats:

  • LOG: Exports logs in a plain .log text file.
  • JSON: Exports logs in a structured .json file, ideal for further data processing or integration with other systems.
  • CSV: Exports logs in a .csv file, suitable for importing into spreadsheet software or databases for analysis.
Customizable Queries:

The method accepts QueryOption parameters, enabling fine-grained control over which logs to export. You can filter by log level, tags, date ranges, or other criteria. Leverage the github.com/Tagliapietra96/logger/queries sub-package for ready-to-use query options.

Export Location:

The exported file will be saved in the folder path configured in the Logger instance using the Folder method. By default, it uses the folder defined during logger setup.

Return Values:
  • File Path: The method returns the full path to the exported file.
  • Error Handling: If the export fails, it returns an error describing the issue.
Example Usage
package main

import (
	"fmt"
	"github.com/Tagliapietra96/logger"
	"github.com/Tagliapietra96/logger/queries"
)

func main() {
	log := logger.New()
	log.Folder("./logs") // Set the export folder

	// Export logs as a JSON file filtered by level and tags
	filePath, err := log.Export(logger.JSON, queries.LevelEqual(logger.Info), queries.HasTags("auth"))
	if err != nil {
		fmt.Println("Error exporting logs:", err)
		return
	}
	fmt.Println("Logs exported to:", filePath)

	// Export logs within a specific date range in CSV format
	filePath, err = log.Export(logger.CSV, queries.DateBetween(time.Now().Add(-24*time.Hour), time.Now()))
	if err != nil {
		fmt.Println("Error exporting logs:", err)
		return
	}
	fmt.Println("Logs exported to:", filePath)
}
Use Cases
  • Backup and Archival: Periodically export logs for long-term storage in .log or .csv format.
  • Data Integration: Export logs in .json format for integration with external tools such as ELK Stack or custom data pipelines.
  • Auditing and Reporting: Generate .csv exports filtered by date range or tags to create detailed audit trails or compliance reports.

Conclusion

Thank you for exploring Logger, a lightweight yet powerful logging system designed to simplify log management for CLI applications. With its user-friendly API, flexible configuration options, and seamless SQLite integration, Logger helps keep your logs organized and accessible. Whether you're building a small utility or a robust command-line tool, Logger offers the essential features to track and analyze application events effectively.

Important Note ⚠️

Please note that Logger has been thoroughly tested only in CLI applications running on Unix-based systems (Linux, macOS, etc.). While it may work in other environments—such as GUI applications or non-Unix platforms—there’s no guarantee of full compatibility or consistent behavior in these contexts. If you use Logger outside its tested environments, please proceed with caution, and feel free to share your experience.

Found a Bug? Have a Suggestion? 💡

I am committed to making Logger as reliable and useful as possible, and your feedback is invaluable! If you encounter any bugs, unexpected behavior, or have ideas for new features, please open an issue on the GitHub repository. I’ll do my best to address your concerns and improve the library based on your input.

Acknowledgements 🙌

Logger wouldn’t be what it is without the amazing contributions of these projects:

I encourage you to visit their repositories, explore their features, and, if you find them useful, consider giving them a ⭐️ to show your support.

Support Logger ❤️

If Logger has been helpful in your project, I’d be incredibly grateful if you could leave a star ⭐️ on the GitHub repository. Your support means a lot and helps other developers discover and benefit from Logger.

Thank you for choosing Logger, and happy logging! 🚀

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ExportType

type ExportType int

ExportType represents the type of the export it is used to specify the type of the export to be done the type can be:

  • JSON: export the logs in JSON format
  • CSV: export the logs in CSV format
  • LOG: export the logs in LOG format
const (
	JSON ExportType = iota // export the logs in JSON
	CSV                    // export the logs in CSV
	LOG                    // export the logs in LOG
)

type LogLevel

type LogLevel int

LogLevel represents the level of the log

  • Debug: used for debugging purposes
  • Info: used for informational messages
  • Warning: used for warning messages
  • Error: used for error messages
  • Fatal: used for fatal messages
const (
	Debug   LogLevel = iota // debug level
	Info                    // info level
	Warning                 // warning level
	Error                   // error level
	Fatal                   // fatal level
)

func (LogLevel) String

func (ls LogLevel) String() string

String returns the string representation of the LogLevel it returns the label of the level in uppercase

type Logger

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

Logger represents the logger configuration structure that holds the configuration options for the logger with the methods to interact with the logger and log messages The logger can be configured with the following options:

  • Folder: (string) the folder path to store the logs data (by default it uses the binary folder) to store the database file, otherwise it will use the current working directory
  • Inline: (bool) if true the logs will be printed inline, otherwise they will be printed in a block
  • Caller: (ShowCallerLevel) the level of caller information to show
  • Timestamp: (ShowTimestampLevel) the level of timestamp information to show
  • ShowTags: (bool) if true the logger will show the tags in the logs
  • Tags: (string) the tags to add to the logs created with this logger
  • SetFatal: (string, string) the title and message to show in the fatal error alert when the Fatal method is called
  • Copy: creates a copy of the logger with the same configurations

The logger has the following methods to log messages:

  • Debug: creates a debug log message in the database (it not will be printed)
  • Info: creates an info log message in the database (it not will be printed)
  • Warn: creates a warning log message in the database (it not will be printed)
  • Error: creates an error log message in the database (it not will be printed)
  • Fatal: creates a fatal log message in the database and exits the program (it not will be printed) it will show an alert with the title and message set with SetFatal (only if the error passed is not nil)
  • PrintDebug: prints a debug log message in the console (it not will be saved in the database)
  • PrintInfo: prints an info log message in the console (it not will be saved in the database)
  • PrintWarn: prints a warning log message in the console (it not will be saved in the database)
  • PrintError: prints an error log message in the console (it not will be saved in the database)
  • PrintFatal: prints a fatal log message in the console and exits the program (it not will be saved in the database) if the error passed is not nil
  • PrintLogs: prints the logs in the database based on the query configurations passed

func New

func New(tags ...string) *Logger

New creates a new logger with the given tags the tags will be added to the logs created with this logger if no tags are passed it will create a logger without tags The new logger will have the following default configurations:

  • folderPath: the bynary folder path (if it fails to get the path it will use an empty string)
  • showTags: false
  • inline: false
  • showCaller: ShowCallerFile
  • showTimestamp: ShowDateTime
  • fatalTitle: "Fatal"
  • fatalMessage: "An error occurred, please check the logs for more information"
  • tags: the tags passed or an empty slice

Check the Logger struct for more information about the logger configurations and the methods to interact with the logger and log messages

func (*Logger) Caller

func (opts *Logger) Caller(level ShowCallerLevel)

Caller sets the level of caller information to show in the logs based on the level parameter the level can be one of the following:

  • ShowCallerFile: shows the file of the caller
  • ShowCallerLine: shows the caller file and line
  • ShowCallerFunction: shows the caller file, line and function
  • HideCaller: hides the caller information

func (*Logger) Copy

func (opts *Logger) Copy() *Logger

Copy creates a copy of the logger with the same configurations

func (*Logger) Debug

func (opts *Logger) Debug(message string, args ...any) error

Debug creates a debug log message in the database with the message and arguments passed it formats the message with the arguments using fmt.Sprintf The new log is created in the database, but it is not printed if it fails to create the log it will return an error

func (*Logger) Error

func (opts *Logger) Error(message string, args ...any) error

Error creates an error log message in the database with the message and arguments passed it formats the message with the arguments using fmt.Sprintf The new log is created in the database, but it is not printed if it fails to create the log it will return an error

func (*Logger) Export

func (opts *Logger) Export(exportType ExportType, queryOptions ...QueryOption) (string, error)

Export exports the logs in the database based on the query options passed to the export type passed the export type defines the format of the exported logs the export type can be one of the following:

  • LOG: exports the logs in a .log file
  • JSON: exports the logs in a .json file
  • CSV: exports the logs in a .csv file

the target folder for the exported file will be the folder path set in the logger

this method returns the path of the exported file and an error if it fails to export the logs

func (*Logger) Fatal

func (opts *Logger) Fatal(e error) error

Fatal creates a fatal log message in the database only if the error passed is not nil it uses the error message as the message of the log The new log is created in the database, but it is not printed it will show an alert with the title and message set with SetFatal this method will exit the program with code 1 if it fails to create the log it will return an error

func (*Logger) Folder

func (opts *Logger) Folder(path string)

Folder sets the folder path to store the logs data Every log created with this logger will be stored in this folder

func (*Logger) Info

func (opts *Logger) Info(message string, args ...any) error

Info creates an info log message in the database with the message and arguments passed it formats the message with the arguments using fmt.Sprintf The new log is created in the database, but it is not printed if it fails to create the log it will return an error

func (*Logger) Inline

func (opts *Logger) Inline(inline bool)

Inline sets the logger to print the logs inline if the inline parameter is true, otherwise it will print the logs in a block (like cards)

func (*Logger) PrintDebug

func (opts *Logger) PrintDebug(message string, args ...any) error

PrintDebug prints a debug log message in the console with the message and arguments passed it formats the message with the arguments using fmt.Sprintf The new log is not created in the database if it fails to print the log it will return an error

func (*Logger) PrintError

func (opts *Logger) PrintError(message string, args ...any) error

PrintError prints an error log message in the console with the message and arguments passed it formats the message with the arguments using fmt.Sprintf The new log is not created in the database if it fails to print the log it will return an error

func (*Logger) PrintFatal

func (opts *Logger) PrintFatal(e error) error

PrintFatal prints a fatal log message in the console and exits the program with the message and arguments passed only if the error passed is not nil it formats the message with the arguments using fmt.Sprintf The new log is not created in the database if it fails to print the log it will return an error

func (*Logger) PrintInfo

func (opts *Logger) PrintInfo(message string, args ...any) error

PrintInfo prints an info log message in the console with the message and arguments passed it formats the message with the arguments using fmt.Sprintf The new log is not created in the database if it fails to print the log it will return an error

func (*Logger) PrintLogs

func (opts *Logger) PrintLogs(queryOptions ...QueryOption) error

PrintLogs prints the logs in the database based on the query options passed if it fails to query the logs it will return an error

func (*Logger) PrintWarn

func (opts *Logger) PrintWarn(message string, args ...any) error

PrintWarn prints a warning log message in the console with the message and arguments passed it formats the message with the arguments using fmt.Sprintf The new log is not created in the database if it fails to print the log it will return an error

func (*Logger) SetFatal

func (opts *Logger) SetFatal(title, message string)

SetFatal sets the title and message to show in the fatal error alert when the Fatal method is called

func (*Logger) SetTags

func (opts *Logger) SetTags(tags ...string)

SetTags sets the tags to the logger this method replaces the current tags with the new ones

func (*Logger) ShowTags

func (opts *Logger) ShowTags(show bool)

ShowTags sets the logger to show the tags in the logs if the show parameter is true, otherwise it will hide the tags

func (*Logger) Tags

func (opts *Logger) Tags(tags ...string)

Tags adds the tags to the logger the tags will be added to the logs created with this logger

func (*Logger) Timestamp

func (opts *Logger) Timestamp(level ShowTimestampLevel)

Timestamp sets the level of timestamp information to show in the logs based on the level parameter the level can be one of the following:

  • ShowFullTimestamp: shows the full timestamp with date and time
  • ShowDateTime: shows the timestamp with date and time
  • ShowTime: shows the timestamp with time only
  • HideTimestamp: hides the timestamp

func (*Logger) Warn

func (opts *Logger) Warn(message string, args ...any) error

Warn creates a warning log message in the database with the message and arguments passed it formats the message with the arguments using fmt.Sprintf The new log is created in the database, but it is not printed if it fails to create the log it will return an error

type QueryOption

type QueryOption func(*strings.Builder)

type ShowCallerLevel

type ShowCallerLevel int

ShowCallerLevel is an enum to define the level of caller information to be shown

const (
	HideCaller         ShowCallerLevel = iota // hide the caller information
	ShowCallerFile                            // show the caller file only main.go
	ShowCallerLine                            // show the caller file and line main.go:10
	ShowCallerFunction                        // show the caller file, line and function main.go:10 - main.main
)

type ShowTimestampLevel

type ShowTimestampLevel int

ShowTimestampLevel is an enum to define the level of timestamp information to be shown the level can be:

  • HideTimestamp: hide the timestamp information
  • ShowDate: show the date 2006-01-02
  • ShowDateTime: show the date and time 2006-01-02 15:04:05
  • ShowFullTimestamp: show the full timestamp Monday 2006-01-02 15:04:05
const (
	HideTimestamp     ShowTimestampLevel = iota // hide the timestamp information
	ShowDate                                    // show the date 2006-01-02
	ShowDateTime                                // show the date and time 2006-01-02 15:04:05
	ShowFullTimestamp                           // show the full timestamp Monday 2006-01-02 15:04:05
)

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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