114 lines
2.6 KiB
Go
114 lines
2.6 KiB
Go
package customlogger
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"log/slog"
|
|
"os"
|
|
"time"
|
|
|
|
"go.mongodb.org/mongo-driver/bson"
|
|
"go.mongodb.org/mongo-driver/mongo"
|
|
"go.mongodb.org/mongo-driver/mongo/options"
|
|
)
|
|
|
|
var LogLevels = map[string]slog.Level{
|
|
"debug": slog.LevelDebug,
|
|
"info": slog.LevelInfo,
|
|
"warn": slog.LevelWarn,
|
|
"error": slog.LevelError,
|
|
}
|
|
var Environment = map[string]string{
|
|
"dev": "development",
|
|
"prod": "production",
|
|
}
|
|
|
|
func NewLogger(env string, lvl slog.Level) *slog.Logger {
|
|
var logHandler slog.Handler
|
|
|
|
err := os.MkdirAll("logs", os.ModePerm)
|
|
if err != nil {
|
|
panic("Failed to create log directory: " + err.Error())
|
|
}
|
|
|
|
file, err := os.OpenFile("logs/app.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
|
|
if err != nil {
|
|
panic("Failed to open log file: " + err.Error())
|
|
}
|
|
|
|
switch env {
|
|
case "development":
|
|
logHandler = slog.NewTextHandler(file, &slog.HandlerOptions{
|
|
Level: lvl,
|
|
})
|
|
default:
|
|
logHandler = slog.NewJSONHandler(file, &slog.HandlerOptions{
|
|
Level: lvl,
|
|
})
|
|
}
|
|
|
|
logger := slog.New(logHandler).With(slog.Group(
|
|
"service_info",
|
|
slog.String("env", env),
|
|
),
|
|
)
|
|
|
|
return logger
|
|
}
|
|
|
|
// MongoLogger wraps a MongoDB connection and logger
|
|
type MongoLogger struct {
|
|
client *mongo.Client
|
|
collection *mongo.Collection
|
|
}
|
|
|
|
// NewMongoLogger creates a new MongoDB-connected logger
|
|
func NewMongoLogger(mongoURI, dbName, collectionName string) (*MongoLogger, error) {
|
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
defer cancel()
|
|
|
|
// 1. Connect to MongoDB with retries
|
|
client, err := mongo.Connect(ctx, options.Client().
|
|
ApplyURI(mongoURI).
|
|
SetServerAPIOptions(options.ServerAPI(options.ServerAPIVersion1)),
|
|
)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("MongoDB connection failed: %w", err)
|
|
}
|
|
|
|
// 2. Verify connection
|
|
err = client.Ping(ctx, nil)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("MongoDB ping failed: %w", err)
|
|
}
|
|
|
|
// 3. Get collection handle
|
|
coll := client.Database(dbName).Collection(collectionName)
|
|
|
|
return &MongoLogger{
|
|
client: client,
|
|
collection: coll,
|
|
}, nil
|
|
}
|
|
|
|
// Log writes a log entry to MongoDB
|
|
func (ml *MongoLogger) Log(level, message string, attrs map[string]interface{}) error {
|
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
|
defer cancel()
|
|
|
|
_, err := ml.collection.InsertOne(ctx, bson.M{
|
|
"timestamp": time.Now(),
|
|
"level": level,
|
|
"message": message,
|
|
"attrs": attrs,
|
|
})
|
|
return err
|
|
}
|
|
|
|
// Close safely disconnects from MongoDB
|
|
func (ml *MongoLogger) Close() error {
|
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
|
defer cancel()
|
|
return ml.client.Disconnect(ctx)
|
|
}
|