aboutsummaryrefslogtreecommitdiff
path: root/weed/worker/log_adapter.go
blob: 7a8f7578fed1b94ed7210dd1f1d5670ce80e881e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
package worker

import (
	"fmt"

	wtasks "github.com/seaweedfs/seaweedfs/weed/worker/tasks"
	wtypes "github.com/seaweedfs/seaweedfs/weed/worker/types"
)

// taskLoggerAdapter adapts a tasks.TaskLogger to the types.Logger interface used by tasks
// so that structured WithFields logs from task implementations are captured into file logs.
type taskLoggerAdapter struct {
	base   wtasks.TaskLogger
	fields map[string]interface{}
}

func newTaskLoggerAdapter(base wtasks.TaskLogger) *taskLoggerAdapter {
	return &taskLoggerAdapter{base: base}
}

// WithFields returns a new adapter instance that includes the provided fields.
func (a *taskLoggerAdapter) WithFields(fields map[string]interface{}) wtypes.Logger {
	// copy fields to avoid mutation by caller
	copied := make(map[string]interface{}, len(fields))
	for k, v := range fields {
		copied[k] = v
	}
	return &taskLoggerAdapter{base: a.base, fields: copied}
}

// Info logs an info message, including any structured fields if present.
func (a *taskLoggerAdapter) Info(msg string, args ...interface{}) {
	if a.base == nil {
		return
	}
	if len(a.fields) > 0 {
		a.base.LogWithFields("INFO", fmt.Sprintf(msg, args...), toStringMap(a.fields))
		return
	}
	a.base.Info(msg, args...)
}

func (a *taskLoggerAdapter) Warning(msg string, args ...interface{}) {
	if a.base == nil {
		return
	}
	if len(a.fields) > 0 {
		a.base.LogWithFields("WARNING", fmt.Sprintf(msg, args...), toStringMap(a.fields))
		return
	}
	a.base.Warning(msg, args...)
}

func (a *taskLoggerAdapter) Error(msg string, args ...interface{}) {
	if a.base == nil {
		return
	}
	if len(a.fields) > 0 {
		a.base.LogWithFields("ERROR", fmt.Sprintf(msg, args...), toStringMap(a.fields))
		return
	}
	a.base.Error(msg, args...)
}

func (a *taskLoggerAdapter) Debug(msg string, args ...interface{}) {
	if a.base == nil {
		return
	}
	if len(a.fields) > 0 {
		a.base.LogWithFields("DEBUG", fmt.Sprintf(msg, args...), toStringMap(a.fields))
		return
	}
	a.base.Debug(msg, args...)
}

// toStringMap converts map[string]interface{} to map[string]interface{} where values are printable.
// The underlying tasks.TaskLogger handles arbitrary JSON values, but our gRPC conversion later
// expects strings; we rely on existing conversion there. Here we keep interface{} to preserve detail.
func toStringMap(in map[string]interface{}) map[string]interface{} {
	out := make(map[string]interface{}, len(in))
	for k, v := range in {
		out[k] = v
	}
	return out
}