/
decorator.go
113 lines (80 loc) · 4.13 KB
/
decorator.go
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
// Copyright 2016 Granitic. All rights reserved.
// Use of this source code is governed by an Apache 2.0 license that can be found in the LICENSE file at the root of this project.
package logger
import (
"github.com/graniticio/granitic/ioc"
"github.com/graniticio/granitic/logging"
"github.com/graniticio/granitic/reflecttools"
"reflect"
)
const expectedApplicationLoggerFieldName string = "Log"
const expectedFrameworkLoggerFieldName string = "FrameworkLogger"
// Injects a Logger into any component with field of type logging.Logger and the name Log.
type applicationLogDecorator struct {
// The application ComponentLoggerManager (as opposed to the framework ComponentLoggerManager)
LoggerManager *logging.ComponentLoggerManager
// Logger to allow this decorator to log messages.
FrameworkLogger logging.Logger
}
// OfInterest returns true if the subject component has a field of type logging.Logger and the name Log.
func (ald *applicationLogDecorator) OfInterest(subject *ioc.Component) bool {
result := false
fieldPresent := reflecttools.HasFieldOfName(subject.Instance, expectedApplicationLoggerFieldName)
frameworkLog := ald.FrameworkLogger
if fieldPresent {
targetFieldType := reflecttools.TypeOfField(subject.Instance, expectedApplicationLoggerFieldName)
typeOfLogger := reflect.TypeOf(ald.FrameworkLogger)
v := reflect.ValueOf(subject.Instance).Elem().FieldByName(expectedApplicationLoggerFieldName)
if typeOfLogger.AssignableTo(targetFieldType) && v.IsNil() {
result = true
}
}
if frameworkLog.IsLevelEnabled(logging.Trace) {
if result {
frameworkLog.LogTracef("%s NEEDS an ApplicationLogger", subject.Name)
} else {
frameworkLog.LogTracef("%s does not need an ApplicationLogger (either no field named %s or incompatible type)", subject.Name, expectedApplicationLoggerFieldName)
}
}
return result
}
// DecorateComponent injects a newly created Logger into the Log field of the subject component.
func (ald *applicationLogDecorator) DecorateComponent(subject *ioc.Component, container *ioc.ComponentContainer) {
logger := ald.LoggerManager.CreateLogger(subject.Name)
reflectComponent := reflect.ValueOf(subject.Instance).Elem()
reflectComponent.FieldByName(expectedApplicationLoggerFieldName).Set(reflect.ValueOf(logger))
}
// Injects a framework logger into Granitic framework components.
type FrameworkLogDecorator struct {
// The framework ComponentLoggerManager (as opposed to the application ComponentLoggerManager)
LoggerManager *logging.ComponentLoggerManager
// Logger to allow this decorator to log messages.
FrameworkLogger logging.Logger
}
// OfInterest returns true if the subject component has a field of type logging.Logger and the name FrameworkLogger.
func (fld *FrameworkLogDecorator) OfInterest(component *ioc.Component) bool {
hasField := reflecttools.HasFieldOfName(component.Instance, expectedFrameworkLoggerFieldName)
v := reflect.ValueOf(component.Instance).Elem().FieldByName(expectedFrameworkLoggerFieldName)
result := hasField && v.IsNil()
frameworkLog := fld.FrameworkLogger
if frameworkLog.IsLevelEnabled(logging.Trace) {
if result {
frameworkLog.LogTracef("%s NEEDS a %s", component.Name, expectedFrameworkLoggerFieldName)
} else {
frameworkLog.LogTracef("%s does not need a %s", component.Name, expectedFrameworkLoggerFieldName)
}
}
return result
}
// DecorateComponent injects a newly created Logger into the FrameworkLogger field of the subject component.
func (fld *FrameworkLogDecorator) DecorateComponent(component *ioc.Component, container *ioc.ComponentContainer) {
logger := fld.LoggerManager.CreateLogger(component.Name)
targetFieldType := reflecttools.TypeOfField(component.Instance, expectedFrameworkLoggerFieldName)
typeOfLogger := reflect.TypeOf(logger)
if typeOfLogger.AssignableTo(targetFieldType) {
reflectComponent := reflect.ValueOf(component.Instance).Elem()
reflectComponent.FieldByName(expectedFrameworkLoggerFieldName).Set(reflect.ValueOf(logger))
} else {
fld.FrameworkLogger.LogErrorf("Unable to inject a FrameworkLogger into component %s because field %s is not of the expected type logger.Logger", component.Name, expectedFrameworkLoggerFieldName)
}
}