- Loggerhead - Logging Library
Loggerhead is a versatile and extendable logging library for Go, designed to enhance the capabilities of standard Go logging with additional features and utilities. Building on top of the slog.Logger
, it provides a robust solution for application logging, including extended log levels, formatted logging methods, and context-aware logging capabilities.
- Extended Log Levels: Includes standard levels like Debug, Info, Warn, and Error, along with custom levels for finer control.
- Formatted Logging: Methods like
Debugf
,Infof
,Warnf
, andErrorf
for formatted output. - Context-Aware Logging: Enhanced logging functionalities that leverage Go's context for richer, more informative log entries.
- Thread-Safe Operations: Ensures safe use in concurrent environments.
- Customizable Handlers: Easily integrate with different logging backends and formats.
To start using Loggerhead, install the package using:
go get -u github.com/lvlcn-t/loggerhead
To start using Loggerhead, you can create a logger instance with default settings or customize it using the logger.Options
struct. Loggerhead provides functions for both general and named loggers, allowing for easy differentiation between log sources.
package main
import (
"github.com/lvlcn-t/loggerhead/logger"
)
func main() {
// Creating a default logger
log := logger.NewLogger()
// Creating a named logger with custom options
opts := logger.Options{Level: "INFO", Format: "JSON"}
log := logger.NewNamedLogger("myServiceLogger", opts)
// Logging a message
log.Info("Hello, world!")
}
Loggerhead provides a comprehensive set of features for advanced logging in Go applications. Here's an overview of its primary functionalities and how to use them effectively:
This function initializes a new logger with default settings or a custom handler if provided. It's the starting point for using Loggerhead in your application.
log := logger.NewLogger()
Creates a new logger with a specified name and a custom handlers if provided. This is useful for identifying logs originating from different parts of your application.
log := logger.NewNamedLogger("MyLogger")
These methods allow you to log messages with a specific format, similar to Printf
functions. They are handy for inserting variable content into your logs.
log.Infof("User %s has logged in", username)
Generates a new context that carries a logger. This is particularly useful in applications where you need to pass the logger through context.
ctx, cancel := logger.NewContextWithLogger(parentContext)
defer cancel()
Retrieves the logger embedded in the provided context. This is essential for getting the logger in different parts of your application where the context is passed.
log := logger.FromContext(ctx)
Embeds a logger into a given context. This can be used to ensure that logging remains consistent across different parts of your application.
newCtx := logger.IntoContext(ctx, log)
Loggerhead offers a middleware function that can be integrated into HTTP server frameworks. This middleware injects the logger into every HTTP request's context, making it easier to log request-specific information.
var handler http.HandlerFunc = func(w http.ResponseWriter, r *http.Request) {}
http.Handle("/", logger.Middleware(context.Background())(handler))
You can configure the logging behavior of the loggerhead library using environment variables. This allows you to adjust configurations without modifying your code.
The following environment variables are supported:
LOG_LEVEL
: Adjusts the minimum log level. This allows you to control the verbosity of the logs. Available options are the standard log levels. For example:DEBUG
,INFO
,WARN
,ERROR
.LOG_FORMAT
: Sets the log format. This allows you to customize the format of the log messages. Available options areTEXT
andJSON
.
Loggerhead is designed to be highly extendable, offering several ways for developers to customize and enhance its functionality:
Developers have the flexibility to use their own slog.Handler
implementations with Loggerhead. This allows for complete control over how logs are processed, formatted, and outputted. Whether integrating with third-party logging services, applying unique log formatting, or implementing custom log filtering logic, you can pass your custom handler to NewLogger
or NewNamedLogger
functions to replace the default behavior.
// Example of using a custom handler
log := logger.NewLogger(logger.Options{
Handler: myCustomHandler,
})
This feature is especially useful for applications with specific logging requirements not covered by the default handlers. By providing your own implementation, you can tailor the logging behavior to fit the needs of your application precisely.
While Loggerhead supports text and JSON formats out of the box, through custom slog.Handler
implementations, developers can define entirely custom formats. This is ideal for adhering to organizational logging standards or enhancing log readability.
Custom handlers also enable integration with various logging backends and services. Whether you're sending logs to a file, a console, a database, or a cloud-based logging platform, you can encapsulate this logic within your handler and use it seamlessly with Loggerhead.
Loggerhead supports integration with OpenTelemetry, allowing for enriched logging with trace and metrics data. This feature is invaluable for applications that require observability and tracing capabilities. By enabling OpenTelemetry support, you can ensure that your logs include relevant tracing information, such as trace IDs and span IDs, linking log entries to specific operations in your application.
To enable OpenTelemetry integration, set the OpenTelemetry
flag to true
in the Options
struct when creating a logger. This will automatically enrich your logs with OpenTelemetry data.
log := logger.NewLogger(logger.Options{
OpenTelemetry: true,
})
When logging within a context that includes OpenTelemetry trace data, Loggerhead automatically includes this information in the logs. This integration allows for seamless correlation between logs and traces, making it easier to debug and monitor distributed applications.
// Assuming the context has been configured with OpenTelemetry
log.InfoContext(ctx, "This is a log message with trace context.")
Loggerhead's OpenTelemetry integration is designed to be flexible, supporting advanced use cases such as:
- Custom Trace Attributes: You can add custom attributes to your traces that are automatically included in your logs, providing more detailed and contextual information for each log entry.
- Baggage: Utilize OpenTelemetry's baggage feature to pass additional metadata through the context, which can then be automatically included in logs for comprehensive tracing and debugging.
// Example of using baggage to add user information to logs
m1, _ := baggage.NewMember("user_id", "12345")
m2, _ := baggage.NewMember("role", "admin")
bag, _ := baggage.New(m1, m2)
ctx := baggage.ContextWithBaggage(context.Background(), bag)
log.InfoContext(ctx, "User action logged with baggage")
- Application Logging: Use Loggerhead for general application logging, capturing information ranging from debug messages to critical errors.
- Request Tracking: In web applications, Loggerhead can be used to log and track HTTP requests, providing valuable insights for debugging and monitoring.
- Contextual Information: With context-aware logging, Loggerhead is ideal for applications that require detailed logs with contextual information, especially useful in microservices and distributed systems.
- Enhanced Observability with OpenTelemetry: When using OpenTelemetry, Loggerhead enriches logs with trace and metrics data, providing comprehensive observability for distributed applications. This includes linking logs to specific operations and tracing information, making it easier to debug and monitor complex systems.
For further examples and detailed usage, including how to implement and integrate custom slog.Handler
instances or use OpenTelemetry with Loggerhead, please refer to the examples directory in our repository.
Contributions are welcome! Please refer to the CONTRIBUTING file for guidelines on how to contribute to this project.
This library is licensed under the MIT License, see the LICENSE file for details.