penambahan loger tersimpan
This commit is contained in:
94
pkg/logger/dynamic_logging_test.go
Normal file
94
pkg/logger/dynamic_logging_test.go
Normal file
@@ -0,0 +1,94 @@
|
||||
package logger
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestDynamicLogging(t *testing.T) {
|
||||
// Pastikan direktori data ada
|
||||
os.RemoveAll("pkg/logger/data")
|
||||
|
||||
t.Run("TestSaveLogText", testSaveLogText)
|
||||
t.Run("TestSaveLogJSON", testSaveLogJSON)
|
||||
t.Run("TestSaveLogToDatabase", testSaveLogToDatabase)
|
||||
t.Run("TestLogAndSave", testLogAndSave)
|
||||
}
|
||||
|
||||
func testSaveLogText(t *testing.T) {
|
||||
logger := New("test-service", INFO, false)
|
||||
|
||||
entry := LogEntry{
|
||||
Timestamp: time.Now().Format(time.RFC3339),
|
||||
Level: "INFO",
|
||||
Service: "test-service",
|
||||
Message: "Test log message",
|
||||
File: "test.go",
|
||||
Line: 10,
|
||||
Fields: map[string]interface{}{
|
||||
"test_field": "test_value",
|
||||
"number": 42,
|
||||
},
|
||||
}
|
||||
|
||||
err := logger.SaveLogText(entry)
|
||||
if err != nil {
|
||||
t.Errorf("SaveLogText failed: %v", err)
|
||||
}
|
||||
|
||||
// Verifikasi file dibuat
|
||||
if _, err := os.Stat("pkg/logger/data/logs.txt"); os.IsNotExist(err) {
|
||||
t.Error("Text log file was not created")
|
||||
}
|
||||
}
|
||||
|
||||
func testSaveLogJSON(t *testing.T) {
|
||||
logger := New("test-service", INFO, false)
|
||||
|
||||
entry := LogEntry{
|
||||
Timestamp: time.Now().Format(time.RFC3339),
|
||||
Level: "INFO",
|
||||
Service: "test-service",
|
||||
Message: "Test JSON log message",
|
||||
File: "test.go",
|
||||
Line: 20,
|
||||
Fields: map[string]interface{}{
|
||||
"json_field": "json_value",
|
||||
"count": 100,
|
||||
},
|
||||
}
|
||||
|
||||
err := logger.SaveLogJSON(entry)
|
||||
if err != nil {
|
||||
t.Errorf("SaveLogJSON failed: %v", err)
|
||||
}
|
||||
|
||||
// Verifikasi file dibuat
|
||||
if _, err := os.Stat("pkg/logger/data/logs.json"); os.IsNotExist(err) {
|
||||
t.Error("JSON log file was not created")
|
||||
}
|
||||
}
|
||||
|
||||
func testSaveLogToDatabase(t *testing.T) {
|
||||
logger := New("test-service", INFO, false)
|
||||
|
||||
entry := LogEntry{
|
||||
Timestamp: time.Now().Format(time.RFC3339),
|
||||
Level: "INFO",
|
||||
Service: "test-service",
|
||||
Message: "Test database log message",
|
||||
File: "test.go",
|
||||
Line: 30,
|
||||
}
|
||||
|
||||
err := logger.SaveLogToDatabase(entry)
|
||||
if err != nil {
|
||||
t.Errorf("SaveLogToDatabase failed: %v", err)
|
||||
}
|
||||
|
||||
// Verifikasi file dibuat (placeholder untuk database)
|
||||
if _, err := os.Stat("pkg/logger/data/database_logs.txt"); os.IsNotExist(err) {
|
||||
t.Error("Database log file was not created")
|
||||
}
|
||||
}
|
||||
105
pkg/logger/example_dynamic_logging.go
Normal file
105
pkg/logger/example_dynamic_logging.go
Normal file
@@ -0,0 +1,105 @@
|
||||
package logger
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
// ExampleDynamicLogging menunjukkan cara menggunakan fungsi penyimpanan log dinamis
|
||||
func ExampleDynamicLogging() {
|
||||
// Buat logger instance
|
||||
logger := New("test-service", DEBUG, false)
|
||||
|
||||
// Contoh 1: Log biasa dengan penyimpanan otomatis
|
||||
fmt.Println("=== Contoh 1: Log biasa dengan penyimpanan otomatis ===")
|
||||
logger.LogAndSave(INFO, "Aplikasi dimulai", map[string]interface{}{
|
||||
"version": "1.0.0",
|
||||
"mode": "development",
|
||||
})
|
||||
|
||||
// Contoh 2: Log dengan request ID
|
||||
fmt.Println("\n=== Contoh 2: Log dengan request ID ===")
|
||||
reqLogger := logger.WithRequestID("req-123456")
|
||||
reqLogger.LogAndSave(INFO, "Request diproses", map[string]interface{}{
|
||||
"endpoint": "/api/v1/users",
|
||||
"method": "GET",
|
||||
"user_id": 1001,
|
||||
})
|
||||
|
||||
// Contoh 3: Log error
|
||||
fmt.Println("\n=== Contoh 3: Log error ===")
|
||||
logger.LogAndSave(ERROR, "Database connection failed", map[string]interface{}{
|
||||
"error": "connection timeout",
|
||||
"timeout": "30s",
|
||||
"host": "localhost:5432",
|
||||
})
|
||||
|
||||
// Contoh 4: Manual save ke berbagai format
|
||||
fmt.Println("\n=== Contoh 4: Manual save ke berbagai format ===")
|
||||
manualEntry := LogEntry{
|
||||
Timestamp: time.Now().Format(time.RFC3339),
|
||||
Level: "INFO",
|
||||
Service: "manual-service",
|
||||
Message: "Manual log entry",
|
||||
RequestID: "manual-req-001",
|
||||
File: "example.go",
|
||||
Line: 42,
|
||||
Fields: map[string]interface{}{
|
||||
"custom_field": "custom_value",
|
||||
"number": 42,
|
||||
},
|
||||
}
|
||||
|
||||
// Simpan manual ke berbagai format
|
||||
if err := SaveLogText(manualEntry); err != nil {
|
||||
fmt.Printf("Error saving text log: %v\n", err)
|
||||
}
|
||||
|
||||
if err := SaveLogJSON(manualEntry); err != nil {
|
||||
fmt.Printf("Error saving JSON log: %v\n", err)
|
||||
}
|
||||
|
||||
if err := SaveLogToDatabase(manualEntry); err != nil {
|
||||
fmt.Printf("Error saving to database log: %v\n", err)
|
||||
}
|
||||
|
||||
// Contoh 5: Log dengan durasi
|
||||
fmt.Println("\n=== Contoh 5: Log dengan durasi ===")
|
||||
start := time.Now()
|
||||
time.Sleep(100 * time.Millisecond) // Simulasi proses
|
||||
duration := time.Since(start)
|
||||
|
||||
logger.LogAndSave(INFO, "Process completed", map[string]interface{}{
|
||||
"operation": "data_processing",
|
||||
"duration": duration.String(),
|
||||
"items": 150,
|
||||
})
|
||||
|
||||
fmt.Println("\n=== Semua log telah disimpan dalam berbagai format ===")
|
||||
fmt.Println("1. Format teks dengan pemisah |: pkg/logger/data/logs.txt")
|
||||
fmt.Println("2. Format JSON: pkg/logger/data/logs.json")
|
||||
fmt.Println("3. Format database (placeholder): pkg/logger/data/database_logs.txt")
|
||||
}
|
||||
|
||||
// ExampleMiddlewareLogging menunjukkan penggunaan dalam middleware
|
||||
func ExampleMiddlewareLogging() {
|
||||
fmt.Println("\n=== Contoh Penggunaan dalam Middleware ===")
|
||||
|
||||
middlewareLogger := New("middleware-service", INFO, false)
|
||||
|
||||
// Simulasi request processing
|
||||
middlewareLogger.LogAndSave(INFO, "Request received", map[string]interface{}{
|
||||
"method": "POST",
|
||||
"path": "/api/v1/auth/login",
|
||||
"client_ip": "192.168.1.100",
|
||||
"user_agent": "Mozilla/5.0",
|
||||
"content_type": "application/json",
|
||||
})
|
||||
|
||||
// Simulasi response
|
||||
middlewareLogger.LogAndSave(INFO, "Response sent", map[string]interface{}{
|
||||
"status_code": 200,
|
||||
"duration": "150ms",
|
||||
"response_size": "2.5KB",
|
||||
})
|
||||
}
|
||||
@@ -376,3 +376,159 @@ func Fatal(msg string, fields ...map[string]interface{}) {
|
||||
func Fatalf(format string, args ...interface{}) {
|
||||
globalLogger.Fatalf(format, args...)
|
||||
}
|
||||
|
||||
// SaveLogText menyimpan log dalam format teks dengan pemisah |
|
||||
func (l *Logger) SaveLogText(entry LogEntry) error {
|
||||
// Format log dengan pemisah |
|
||||
logLine := fmt.Sprintf("%s|%s|%s|%s|%s|%s|%s|%s:%d",
|
||||
entry.Timestamp,
|
||||
entry.Level,
|
||||
entry.Service,
|
||||
entry.Message,
|
||||
entry.RequestID,
|
||||
entry.CorrelationID,
|
||||
entry.Duration,
|
||||
entry.File,
|
||||
entry.Line)
|
||||
|
||||
// Tambahkan fields jika ada
|
||||
if len(entry.Fields) > 0 {
|
||||
fieldsStr := ""
|
||||
for k, v := range entry.Fields {
|
||||
fieldsStr += fmt.Sprintf("|%s=%v", k, v)
|
||||
}
|
||||
logLine += fieldsStr
|
||||
}
|
||||
logLine += "\n"
|
||||
|
||||
// Buat direktori jika belum ada
|
||||
dirPath := "pkg/logger/data"
|
||||
if err := os.MkdirAll(dirPath, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Tulis ke file
|
||||
filePath := dirPath + "/logs.txt"
|
||||
f, err := os.OpenFile(filePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
if _, err := f.WriteString(logLine); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SaveLogJSON menyimpan log dalam format JSON
|
||||
func (l *Logger) SaveLogJSON(entry LogEntry) error {
|
||||
jsonData, err := json.Marshal(entry)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Buat direktori jika belum ada
|
||||
dirPath := "pkg/logger/data"
|
||||
if err := os.MkdirAll(dirPath, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Tulis ke file
|
||||
filePath := dirPath + "/logs.json"
|
||||
f, err := os.OpenFile(filePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
if _, err := f.WriteString(string(jsonData) + "\n"); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SaveLogToDatabase menyimpan log ke database
|
||||
func (l *Logger) SaveLogToDatabase(entry LogEntry) error {
|
||||
// Implementasi penyimpanan ke database
|
||||
// Ini adalah contoh implementasi, sesuaikan dengan struktur database Anda
|
||||
|
||||
// Untuk saat ini, kita akan simpan ke file sebagai placeholder
|
||||
// Anda dapat mengganti ini dengan koneksi database yang sesuai
|
||||
dbLogLine := fmt.Sprintf("DB_LOG: %s|%s|%s|%s\n",
|
||||
entry.Timestamp, entry.Level, entry.Service, entry.Message)
|
||||
|
||||
dirPath := "pkg/logger/data"
|
||||
if err := os.MkdirAll(dirPath, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
filePath := dirPath + "/database_logs.txt"
|
||||
f, err := os.OpenFile(filePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
if _, err := f.WriteString(dbLogLine); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// LogAndSave melakukan logging dan menyimpan ke semua format
|
||||
func (l *Logger) LogAndSave(level LogLevel, msg string, fields ...map[string]interface{}) {
|
||||
// Panggil fungsi log biasa
|
||||
l.log(level, msg, nil, fields...)
|
||||
|
||||
// Dapatkan entry log yang baru dibuat
|
||||
_, file, line, ok := runtime.Caller(2)
|
||||
var callerFile string
|
||||
var callerLine int
|
||||
if ok {
|
||||
parts := strings.Split(file, "/")
|
||||
if len(parts) > 2 {
|
||||
callerFile = strings.Join(parts[len(parts)-2:], "/")
|
||||
} else {
|
||||
callerFile = file
|
||||
}
|
||||
callerLine = line
|
||||
}
|
||||
|
||||
mergedFields := make(map[string]interface{})
|
||||
for _, f := range fields {
|
||||
for k, v := range f {
|
||||
mergedFields[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
entry := LogEntry{
|
||||
Timestamp: time.Now().Format(time.RFC3339),
|
||||
Level: levelStrings[level],
|
||||
Service: l.serviceName,
|
||||
Message: msg,
|
||||
File: callerFile,
|
||||
Line: callerLine,
|
||||
Fields: mergedFields,
|
||||
}
|
||||
|
||||
// Simpan ke semua format
|
||||
go func() {
|
||||
l.SaveLogText(entry)
|
||||
l.SaveLogJSON(entry)
|
||||
l.SaveLogToDatabase(entry)
|
||||
}()
|
||||
}
|
||||
|
||||
// Global fungsi untuk menyimpan log
|
||||
func SaveLogText(entry LogEntry) error {
|
||||
return globalLogger.SaveLogText(entry)
|
||||
}
|
||||
|
||||
func SaveLogJSON(entry LogEntry) error {
|
||||
return globalLogger.SaveLogJSON(entry)
|
||||
}
|
||||
|
||||
func SaveLogToDatabase(entry LogEntry) error {
|
||||
return globalLogger.SaveLogToDatabase(entry)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user