Files
crawlab/core/utils/logger.go
Marvin Zhang 17f8917d0a chore: update dependencies and enhance gRPC services
- Updated various dependencies in go.mod and go.sum files, including cloud.google.com/go/compute/metadata to v0.5.2, google.golang.org/grpc to v1.69.2, and google.golang.org/protobuf to v1.36.1.
- Refactored gRPC service definitions to use the latest protoc-gen-go and protoc versions, ensuring compatibility with the latest gRPC-Go features.
- Introduced a new logger utility in core/utils/logger.go to improve logging capabilities across the application.
- Added a README.md for gRPC setup and compilation guidance, enhancing developer experience.
- Improved the Python installation script to handle version listing more effectively and ensure user-specific environment setup.
2024-12-25 17:46:49 +08:00

199 lines
4.3 KiB
Go

package utils
import (
"errors"
"fmt"
"github.com/crawlab-team/crawlab/trace"
"io"
"os"
"sync"
"time"
"github.com/apex/log"
"github.com/apex/log/handlers/json"
"github.com/apex/log/handlers/text"
)
var logger = NewLogger("Utils")
// Logger represents a logger with a specific service prefix.
type Logger struct {
prefix string
}
type ServiceLoggerOption func(logger *Logger)
func WithHandler(handlerType string, output *os.File) ServiceLoggerOption {
return func(logger *Logger) {
SetHandler(handlerType, output)
}
}
// NewLogger creates a new logger with the given service name as a prefix.
func NewLogger(prefix string, opts ...ServiceLoggerOption) *Logger {
logger := &Logger{
prefix: prefix,
}
if len(opts) == 0 {
SetConsoleHandler()
} else {
for _, opt := range opts {
opt(logger)
}
}
return logger
}
// Debug logs a debug message.
func (l *Logger) Debug(message string) {
log.Debug(l.getFormat(message))
}
// Info logs an informational message.
func (l *Logger) Info(message string) {
log.Info(l.getFormat(message))
}
// Warn logs a warning message.
func (l *Logger) Warn(message string) {
log.Warn(l.getFormat(message))
}
// Error logs an error message.
func (l *Logger) Error(message string) {
log.Error(l.getFormat(message))
if IsDev() {
trace.PrintError(errors.New(message))
}
}
// Fatal logs a fatal message.
func (l *Logger) Fatal(message string) {
log.Fatal(l.getFormat(message))
if IsDev() {
trace.PrintError(errors.New(message))
}
}
// Debugf logs a debug message with formatted content.
func (l *Logger) Debugf(format string, args ...interface{}) {
log.Debugf(l.getFormat(format), args...)
}
// Infof logs an informational message with formatted content.
func (l *Logger) Infof(format string, args ...interface{}) {
log.Infof(l.getFormat(format), args...)
}
// Warnf logs a warning message with formatted content.
func (l *Logger) Warnf(format string, args ...interface{}) {
log.Warnf(l.getFormat(format), args...)
}
// Errorf logs an error message with formatted content.
func (l *Logger) Errorf(format string, args ...interface{}) {
log.Errorf(l.getFormat(format), args...)
if IsDev() {
trace.PrintError(errors.New(fmt.Sprintf(format, args...)))
}
}
// Fatalf logs an error message with formatted content.
func (l *Logger) Fatalf(format string, args ...interface{}) {
log.Fatalf(l.getFormat(format), args...)
if IsDev() {
trace.PrintError(errors.New(fmt.Sprintf(format, args...)))
}
}
func (l *Logger) getFormat(format string) string {
timestamp := time.Now().Local().Format("2006-01-02 15:04:05")
return fmt.Sprintf("[%s] [%s] %s", timestamp, l.prefix, format)
}
type LogHandler struct {
mu sync.Mutex
}
func handleLog(w io.Writer, e *log.Entry) error {
color := text.Colors[e.Level]
level := text.Strings[e.Level]
names := e.Fields.Names()
fmt.Fprintf(w, "\033[%dm%6s\033[0m %-25s", color, level, e.Message)
for _, name := range names {
fmt.Fprintf(w, " \033[%dm%s\033[0m=%v", color, name, e.Fields.Get(name))
}
fmt.Fprintln(w)
return nil
}
// MultiHandler is a handler that routes logs to stdout/stderr based on level
type MultiHandler struct {
mu sync.Mutex
}
// NewMultiHandler creates a handler that routes logs to stdout/stderr based on level
func NewMultiHandler() *MultiHandler {
return &MultiHandler{
mu: sync.Mutex{},
}
}
// HandleLog implements log.Handler interface
func (h *MultiHandler) HandleLog(e *log.Entry) error {
h.mu.Lock()
defer h.mu.Unlock()
// Route to stderr for warn, error, and fatal
if e.Level <= log.WarnLevel {
return handleLog(os.Stdout, e)
}
// Route to stdout for debug and info
return handleLog(os.Stderr, e)
}
type ConsoleHandler struct {
mu sync.Mutex
}
func NewConsoleHandler() *ConsoleHandler {
return &ConsoleHandler{
mu: sync.Mutex{},
}
}
func (h *ConsoleHandler) HandleLog(e *log.Entry) error {
h.mu.Lock()
defer h.mu.Unlock()
return handleLog(os.Stdout, e)
}
// SetHandler to include the new option
func SetHandler(handlerType string, output *os.File) {
switch handlerType {
case "json":
log.SetHandler(json.New(output))
case "text":
log.SetHandler(text.New(output))
case "split":
SetMultiHandler()
default:
SetConsoleHandler()
}
}
func SetMultiHandler() {
log.SetHandler(NewMultiHandler())
}
func SetConsoleHandler() {
log.SetHandler(NewConsoleHandler())
}