Skip to content

Commit e84ee33

Browse files
authored
Merge pull request #45 from gatewayd-io/add-logging-adapter
Add logging adapter for the plugin system
2 parents 6a4ba89 + 6c17a97 commit e84ee33

File tree

4 files changed

+230
-11
lines changed

4 files changed

+230
-11
lines changed

cmd/run.go

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ var runCmd = &cobra.Command{
9292
// Create a new logger from the config
9393
loggerCfg := loggerConfig()
9494
logger := logging.NewLogger(loggerCfg)
95-
// TODO: Use https://github.com/dcarbone/zadapters to adapt hclog to zerolog
95+
9696
// This is a notification hook, so we don't care about the result.
9797
data, err := structpb.NewStruct(map[string]interface{}{
9898
"timeFormat": loggerCfg.TimeFormat,
@@ -215,12 +215,6 @@ var runCmd = &cobra.Command{
215215
// Internal event-loop load balancing options
216216
gnet.WithLoadBalancing(serverConfig.LoadBalancer),
217217

218-
// Logger options
219-
// TODO: This is a temporary solution and will be replaced.
220-
// gnet.WithLogger(logrus.New()),
221-
// gnet.WithLogPath("./gnet.log"),
222-
// gnet.WithLogLevel(zapcore.DebugLevel),
223-
224218
// Buffer options
225219
gnet.WithReadBufferCap(serverConfig.ReadBufferCap),
226220
gnet.WithWriteBufferCap(serverConfig.WriteBufferCap),

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ go 1.19
55
require (
66
github.com/fergusstrange/embedded-postgres v1.19.0
77
github.com/google/go-cmp v0.5.9
8+
github.com/hashicorp/go-hclog v1.4.0
89
github.com/hashicorp/go-plugin v1.4.8
910
github.com/knadh/koanf v1.4.4
1011
github.com/mitchellh/mapstructure v1.5.0
@@ -21,7 +22,6 @@ require (
2122
github.com/fatih/color v1.13.0 // indirect
2223
github.com/fsnotify/fsnotify v1.4.9 // indirect
2324
github.com/golang/protobuf v1.5.2 // indirect
24-
github.com/hashicorp/go-hclog v1.4.0 // indirect
2525
github.com/hashicorp/yamux v0.1.1 // indirect
2626
github.com/inconshreveable/mousetrap v1.1.0 // indirect
2727
github.com/lib/pq v1.10.7 // indirect

logging/hclog_adapter.go

Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
package logging
2+
3+
import (
4+
"fmt"
5+
"io"
6+
"log"
7+
"reflect"
8+
9+
"github.com/hashicorp/go-hclog"
10+
"github.com/rs/zerolog"
11+
)
12+
13+
// NewHcLogAdapter creates a new hclog.Logger that wraps a zerolog.Logger.
14+
func NewHcLogAdapter(logger *zerolog.Logger, name string) hclog.Logger {
15+
return &HcLogAdapter{logger, name, nil}
16+
}
17+
18+
type HcLogAdapter struct {
19+
logger *zerolog.Logger
20+
name string
21+
22+
impliedArgs []interface{}
23+
}
24+
25+
func (h HcLogAdapter) Log(level hclog.Level, msg string, args ...interface{}) {
26+
switch level {
27+
case hclog.Off:
28+
return
29+
case hclog.NoLevel:
30+
return
31+
case hclog.Trace:
32+
h.Trace(msg, args...)
33+
case hclog.Debug:
34+
h.Debug(msg, args...)
35+
case hclog.Info:
36+
h.Info(msg, args...)
37+
case hclog.Warn:
38+
h.Warn(msg, args...)
39+
case hclog.Error:
40+
h.Error(msg, args...)
41+
}
42+
}
43+
44+
func (h HcLogAdapter) Trace(msg string, args ...interface{}) {
45+
h.logger.Trace().Fields(ToMap(args)).Msg(msg)
46+
}
47+
48+
func (h HcLogAdapter) Debug(msg string, args ...interface{}) {
49+
h.logger.Debug().Fields(ToMap(args)).Msg(msg)
50+
}
51+
52+
func (h HcLogAdapter) Info(msg string, args ...interface{}) {
53+
h.logger.Info().Fields(ToMap(args)).Msg(msg)
54+
}
55+
56+
func (h HcLogAdapter) Warn(msg string, args ...interface{}) {
57+
h.logger.Warn().Fields(ToMap(args)).Msg(msg)
58+
}
59+
60+
func (h HcLogAdapter) Error(msg string, args ...interface{}) {
61+
h.logger.Error().Fields(ToMap(args)).Msg(msg)
62+
}
63+
64+
func (h HcLogAdapter) GetLevel() hclog.Level {
65+
switch h.logger.GetLevel() {
66+
case zerolog.Disabled:
67+
return hclog.Off
68+
case zerolog.NoLevel:
69+
return hclog.NoLevel
70+
case zerolog.TraceLevel:
71+
return hclog.Trace
72+
case zerolog.DebugLevel:
73+
return hclog.Debug
74+
case zerolog.InfoLevel:
75+
return hclog.Info
76+
case zerolog.WarnLevel:
77+
return hclog.Warn
78+
case zerolog.ErrorLevel:
79+
return hclog.Error
80+
case zerolog.FatalLevel:
81+
return hclog.Error
82+
case zerolog.PanicLevel:
83+
return hclog.Error
84+
}
85+
return hclog.NoLevel
86+
}
87+
88+
func (h HcLogAdapter) IsTrace() bool {
89+
return h.logger.GetLevel() >= zerolog.TraceLevel
90+
}
91+
92+
func (h HcLogAdapter) IsDebug() bool {
93+
return h.logger.GetLevel() >= zerolog.DebugLevel
94+
}
95+
96+
func (h HcLogAdapter) IsInfo() bool {
97+
return h.logger.GetLevel() >= zerolog.InfoLevel
98+
}
99+
100+
func (h HcLogAdapter) IsWarn() bool {
101+
return h.logger.GetLevel() >= zerolog.WarnLevel
102+
}
103+
104+
func (h HcLogAdapter) IsError() bool {
105+
return h.logger.GetLevel() >= zerolog.ErrorLevel
106+
}
107+
108+
func (h HcLogAdapter) ImpliedArgs() []interface{} {
109+
// Not supported
110+
return nil
111+
}
112+
113+
func (h HcLogAdapter) With(args ...interface{}) hclog.Logger {
114+
logger := h.logger.With().Fields(ToMap(args)).Logger()
115+
return NewHcLogAdapter(&logger, h.Name())
116+
}
117+
118+
func (h HcLogAdapter) Name() string {
119+
return h.name
120+
}
121+
122+
func (h HcLogAdapter) Named(name string) hclog.Logger {
123+
return NewHcLogAdapter(h.logger, name)
124+
}
125+
126+
func (h HcLogAdapter) ResetNamed(name string) hclog.Logger {
127+
return &h
128+
}
129+
130+
func (h *HcLogAdapter) SetLevel(level hclog.Level) {
131+
leveledLog := h.logger.Level(convertLevel(level))
132+
h.logger = &leveledLog
133+
}
134+
135+
func (h HcLogAdapter) StandardLogger(opts *hclog.StandardLoggerOptions) *log.Logger {
136+
if opts == nil {
137+
opts = &hclog.StandardLoggerOptions{}
138+
}
139+
return log.New(h.StandardWriter(opts), "", 0)
140+
}
141+
142+
func (h HcLogAdapter) StandardWriter(opts *hclog.StandardLoggerOptions) io.Writer {
143+
v := reflect.ValueOf(h.logger)
144+
w := v.FieldByName("w")
145+
writer, ok := w.Interface().(zerolog.LevelWriter)
146+
if !ok {
147+
return nil
148+
}
149+
return writer
150+
}
151+
152+
func convertLevel(level hclog.Level) zerolog.Level {
153+
switch level {
154+
case hclog.Off:
155+
return zerolog.Disabled
156+
case hclog.NoLevel:
157+
return zerolog.NoLevel
158+
case hclog.Trace:
159+
return zerolog.TraceLevel
160+
case hclog.Debug:
161+
return zerolog.DebugLevel
162+
case hclog.Info:
163+
return zerolog.InfoLevel
164+
case hclog.Warn:
165+
return zerolog.WarnLevel
166+
case hclog.Error:
167+
return zerolog.ErrorLevel
168+
}
169+
return zerolog.NoLevel
170+
}
171+
172+
func ToMap(keyValues []interface{}) map[string]interface{} {
173+
mapped := map[string]interface{}{}
174+
175+
if len(keyValues) == 0 {
176+
return mapped
177+
}
178+
179+
if len(keyValues)%2 == 1 {
180+
keyValues = append(keyValues, nil)
181+
}
182+
183+
for i := 0; i < len(keyValues); i += 2 {
184+
merge(mapped, keyValues[i], keyValues[i+1])
185+
}
186+
187+
return mapped
188+
}
189+
190+
func merge(mapped map[string]interface{}, key, value interface{}) {
191+
var casted string
192+
193+
switch castedKey := key.(type) {
194+
case string:
195+
casted = castedKey
196+
case fmt.Stringer:
197+
casted = safeString(castedKey)
198+
default:
199+
casted = fmt.Sprint(castedKey)
200+
}
201+
202+
mapped[casted] = value
203+
}
204+
205+
//nolint:nonamedreturns
206+
func safeString(str fmt.Stringer) (s string) {
207+
defer func() {
208+
if panicVal := recover(); panicVal != nil {
209+
if v := reflect.ValueOf(str); v.Kind() == reflect.Ptr && v.IsNil() {
210+
s = "NULL"
211+
} else {
212+
panic(panicVal)
213+
}
214+
}
215+
}()
216+
217+
s = str.String()
218+
219+
return
220+
}

plugin/registry.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"os/exec"
66

7+
"github.com/gatewayd-io/gatewayd/logging"
78
pluginV1 "github.com/gatewayd-io/gatewayd/plugin/v1"
89
"github.com/gatewayd-io/gatewayd/pool"
910
goplugin "github.com/hashicorp/go-plugin"
@@ -13,9 +14,10 @@ import (
1314
)
1415

1516
const (
16-
DefaultMinPort uint = 50000
17-
DefaultMaxPort uint = 60000
18-
PluginPriorityStart uint = 1000
17+
DefaultMinPort uint = 50000
18+
DefaultMaxPort uint = 60000
19+
PluginPriorityStart uint = 1000
20+
LoggerName string = "plugin"
1921
)
2022

2123
var handshakeConfig = goplugin.HandshakeConfig{
@@ -140,6 +142,8 @@ func (reg *RegistryImpl) LoadPlugins(pluginConfig *koanf.Koanf) {
140142
// have a priority of 0 to 999, and user-defined plugins have a priority of 1000 or greater.
141143
plugin.Priority = Priority(PluginPriorityStart + uint(priority))
142144

145+
logAdapter := logging.NewHcLogAdapter(&reg.hooksConfig.Logger, LoggerName)
146+
143147
plugin.client = goplugin.NewClient(
144148
&goplugin.ClientConfig{
145149
HandshakeConfig: handshakeConfig,
@@ -149,6 +153,7 @@ func (reg *RegistryImpl) LoadPlugins(pluginConfig *koanf.Koanf) {
149153
goplugin.ProtocolGRPC,
150154
},
151155
// SecureConfig: nil,
156+
Logger: logAdapter,
152157
Managed: true,
153158
MinPort: DefaultMinPort,
154159
MaxPort: DefaultMaxPort,

0 commit comments

Comments
 (0)