Introducing Logz: A Secure and Flexible Logger for Go Developers and General Use! đ
Opening Hook
Are you tired of wrestling with clunky, insecure logging systems in your Go applications? Imagine having a logger that not only packs powerful features and robust security into a single package but also delivers an incredibly smooth developer experience. Meet Logzâthe open-source logging solution that transforms your logging workflow with flexibility, security, and integrated notification capabilities. Whether youâre developing locally or deploying in production, Logz is here to make your logging process seamless.
Main Content
Why Logz?
Every good application needs reliable logging. Yet too often, logging is treated as an afterthought. With Logz, weâve turned logging into a first-class experience by focusing on two essential pillars: developer experience and security. Hereâs how Logz stands out:
Metadata-Driven Logging:
Easily attach contextâlikerequestId
,user
, or other relevant fieldsâto every log entry. This isnât just extra data; itâs actionable intelligence that speeds up debugging and monitoring.Secure Build Practices:
Logz leverages Goâs-trimpath
flag to strip sensitive build paths from binaries, and we recommend compressing your executables with UPX to ensure theyâre lightweight and secure. With these practices built in, secure logging isnât an afterthoughtâitâs part of the design.Flexible Output Options:
Whether you prefer logging to the console during development or to files in production, Logz gives you full control. Its CLI flags let you easily switch outputs, adjust formats, and donât force you into one rigid workflow.
Key Features
Logz is built to cover all your logging needs while extending its functionality further:
Multiple Log Formats:
Choose between human-friendly text logs and machine-parsable JSON to fit your workflow.Neatly Aligned Output:
Enjoy output where timestamps, log levels, and metadata are neatly aligned. For text logs, metadata is printed on a new indented line, enhancing readability without cluttering your primary log message.Comprehensive CLI Control:
With flags such as--msg
,--output
,--metadata
, and--format
, you have fine-grained control over every aspect of your log entries.Notification Integrations:
Logz can do more than just print logs. Its built-in notifier system supports HTTP webhooks, ZeroMQ, and DBus. This means you can set up real-time alerts whenever critical events occur, directly integrating with your existing monitoring systems.Advanced First-Run Installer:
For a truly seamless experience, Logz features an intelligent first-run installer. Upon initial execution, Logz checks if itâs properly installedâand if not, it can automatically copy itself to the appropriate directory (e.g.,$HOME/.local/bin
for non-root users or/usr/local/bin
for root users), and update the PATH so the tool is immediately accessible.
Extended Code Examples
Example 1: Basic Debug Logging with Metadata
Log a debug message with contextual metadata using:
logz debug \
--msg "Debugging the latest feature with ease!" \
--output "stdout" \
--metadata requestId=12345,user=admin
Expected Output:
[2025-03-02T03:35:13Z] đ DEBUG - Debugging the latest feature with ease!
{"requestId":"12345","user":"admin"}
Each log entry is timestamped and clearly displays the log level along with your message. The metadata, shown on an indented new line, ensures additional context is visible without cluttering the primary message.
Example 2: Logging to File in JSON Format
For production, you can output logs in JSON format:
logz info \
--msg "Service started successfully." \
--output "/var/log/myapp/service.log" \
--format json \
--metadata service=auth,version=v1.0.2
Expected Output (JSON):
{
"timestamp": "2025-03-02T03:40:00Z",
"level": "INFO",
"message": "Service started successfully.",
"metadata": {
"service": "auth",
"version": "v1.0.2"
}
}
This format is ideal for integration with log aggregators and monitoring systems.
Example 3: Integrating Logz in a Microservice Web Application
Below is a snippet showing how to integrate Logz in an HTTP server:
package main
import (
"fmt"
"net/http"
"github.com/faelmori/logz/logger" // Adjust the import path as needed
)
func main() {
// Initialize the logger with a custom prefix.
log := logger.NewLogger("WebAPI: ")
// Define an HTTP handler to log request details.
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
log.Info("Received request", map[string]interface{}{
"method": r.Method,
"path": r.URL.Path,
})
fmt.Fprintf(w, "Hello, world!")
})
// Start the HTTP server.
log.Info("Starting server on port 8080", nil)
if err := http.ListenAndServe(":8080", nil); err != nil {
log.Fatal("Server failed to start", map[string]interface{}{"error": err})
}
}
This example shows how every request and error is logged with useful metadata, making troubleshooting much easier.
Example 4: Notifier Integration for Real-Time Alerts
Logzâs notifier system allows you to send alerts via webhooks, ZeroMQ, or DBus. Hereâs a brief example of how you might set up a notifier for critical errors:
package main
import (
"github.com/faelmori/logz/logger"
"time"
)
func main() {
// Initialize the logger and set global metadata.
log := logger.NewLogger("AlertService: ")
log.SetMetadata("service", "payment")
log.SetMetadata("env", "production")
// Simulate an error to trigger a notifier.
log.Error("Payment transaction failed", map[string]interface{}{
"transactionId": "txn_987654321",
"timestamp": time.Now().Format(time.RFC3339),
})
}
With the notifier setup in your configuration, this log entry might trigger an HTTP alert, a ZeroMQ message, or a DBus notificationâwhatever best suits your environment.
Example 5: Advanced First-Run Installer Logic
To address environment configuration automatically, Logz includes a first-run installer that checks if the binary is properly installed and, if not, copies itself to an appropriate directory and updates the PATH:
package main
import (
"fmt"
"io"
"os"
"os/exec"
"path/filepath"
"strings"
)
// isInPath checks if the current executable's directory is present in the PATH.
func isInPath() bool {
pathEnv := os.Getenv("PATH")
exePath, err := os.Executable()
if err != nil {
return false
}
exeDir := filepath.Dir(exePath)
return strings.Contains(pathEnv, exeDir)
}
// firstRunInstaller checks if Logz is installed in the expected location and updates the PATH if necessary.
func firstRunInstaller() {
configFile := filepath.Join(os.Getenv("HOME"), ".logzconfig")
if _, err := os.Stat(configFile); os.IsNotExist(err) {
fmt.Println("It looks like this is your first time using Logz.")
fmt.Print("Would you like to install Logz for easier access? (Y/n): ")
var response string
fmt.Scanln(&response)
if strings.ToLower(response) == "y" || response == "" {
exePath, err := os.Executable()
if err != nil {
fmt.Printf("Error obtaining executable path: %v\n", err)
return
}
targetDir := "/usr/local/bin"
if os.Geteuid() != 0 {
targetDir = filepath.Join(os.Getenv("HOME"), ".local", "bin")
}
target := filepath.Join(targetDir, "logz")
cmd := exec.Command("cp", exePath, target)
if err := cmd.Run(); err != nil {
fmt.Printf("Installation error: %v\n", err)
return
}
fmt.Printf("Logz installed to %s.\n", target)
// Update PATH automatically by determining the user's shell config.
shellConfig := ""
switch filepath.Base(os.Getenv("SHELL")) {
case "bash":
shellConfig = filepath.Join(os.Getenv("HOME"), ".bashrc")
case "zsh":
shellConfig = filepath.Join(os.Getenv("HOME"), ".zshrc")
default:
shellConfig = filepath.Join(os.Getenv("HOME"), ".profile")
}
fmt.Printf("Adding %s to PATH in %s...\n", targetDir, shellConfig)
f, err := os.OpenFile(shellConfig, os.O_APPEND|os.O_WRONLY, 0644)
if err == nil {
_, err := f.WriteString(fmt.Sprintf("\nexport PATH=%s:$PATH\n", targetDir))
if err == nil {
fmt.Printf("PATH updated in %s. Run 'source %s' to apply changes.\n", shellConfig, shellConfig)
}
f.Close()
} else {
fmt.Printf("Failed to update %s. Please add %s to your PATH manually.\n", shellConfig, targetDir)
}
// Write to config file to avoid asking again.
os.WriteFile(configFile, []byte("installed=true\n"), 0644)
} else {
os.WriteFile(configFile, []byte("skip_install=true\n"), 0644)
fmt.Println("Installation skipped. You can install it later manually.")
}
}
}
func main() {
// Try to run the first-run installer
firstRunInstaller()
// Continue with the normal program flow
fmt.Println("Logz is ready to use.")
}
This code checks whether it's the first time Logz is being run, asks the user if theyâd like it installed for easier access, and then automatically copies the executable and updates the PATH by modifying the appropriate shell configuration file. This automation greatly improves usability for users who may not be comfortable with manual PATH configuration.
Project Highlights
Open Source on GitHub:
Dive into the source, contribute your improvements, or star the repository if Logz resonates with you. See it on GitHub.Detailed Documentation:
Comprehensive API references and integration guides are fully available on pkg.go.dev, making Logz easy to integrate into your projects.
Conclusion and Call-to-Action
Logz is not just a loggerâitâs a complete observability tool for modern Go applications. It combines secure build practices, flexible output, rich metadata handling, and even smart notification integrations. Its advanced first-run installer ensures that Logz is set up perfectly on your system without the usual hassles.
If Logz simplifies your logging, consider giving it a try in your next Go project and sharing your thoughts on GitHub. Your feedback and support help us build a smarter, faster, and more secure logging ecosystemâone log entry at a time!
Top comments (0)