Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

create logger wrapper to store additional information #697

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions logging/annotated_logger.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// SPDX-License-Identifier: Apache-2.0

package logging

// AnnotatedLogger wraps a Logger and appends information to
// each one of the received logs.
type AnnotatedLogger struct {
appendAnnotation string
wrapped Logger
}

// NewAnnotatedLogger creates and returns a Logger object
func NewAnnotatedLogger(l Logger, appendAnnotation string) (AnnotatedLogger, error) {
if al, ok := l.(AnnotatedLogger); ok {
// if the given logger is already an annotated logger, we
// can combine the two appended anotations and save a wrap around
if len(al.appendAnnotation) > 0 {
appendAnnotation = al.appendAnnotation + " " + appendAnnotation
}
l = al.wrapped
}
return AnnotatedLogger{
appendAnnotation: appendAnnotation,
wrapped: l,
}, nil
}

// Debug logs a message using DEBUG as log level.
func (l AnnotatedLogger) Debug(v ...interface{}) {
l.wrapped.Debug(l.appendLog(v)...)
}

// Info logs a message using INFO as log level.
func (l AnnotatedLogger) Info(v ...interface{}) {
l.wrapped.Info(l.appendLog(v)...)
}

// Warning logs a message using WARNING as log level.
func (l AnnotatedLogger) Warning(v ...interface{}) {
l.wrapped.Warning(l.appendLog(v)...)
}

// Error logs a message using ERROR as log level.
func (l AnnotatedLogger) Error(v ...interface{}) {
l.wrapped.Error(l.appendLog(v)...)
}

// Critical logs a message using CRITICAL as log level.
func (l AnnotatedLogger) Critical(v ...interface{}) {
l.wrapped.Critical(l.appendLog(v)...)
}

// Fatal is equivalent to l.Critical(fmt.Sprint()) followed by a call to os.Exit(1).
func (l AnnotatedLogger) Fatal(v ...interface{}) {
l.wrapped.Fatal(l.appendLog(v)...)
}

func (l AnnotatedLogger) appendLog(v []interface{}) []interface{} {
if len(l.appendAnnotation) == 0 {
return v
}
msg := make([]interface{}, len(v)+1)
copy(msg, v)
msg[len(v)] = l.appendAnnotation
return msg
}
48 changes: 48 additions & 0 deletions logging/annotated_logger_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// SPDX-License-Identifier: Apache-2.0

package logging

import (
"bytes"
"strings"
"testing"
)

func TestRegularLogger(t *testing.T) {
buff := bytes.NewBuffer(make([]byte, 1024))
bl, _ := NewLogger("DEBUG", buff, "PREFIX")

bl.Info("A", "B", "C")

s := buff.String()
if !strings.Contains(s, "A B C") {
t.Errorf("missing: A B C : %s", s)
}
}

func TestNewAnnotatedLogger(t *testing.T) {
buff := bytes.NewBuffer(make([]byte, 1024))
bl, _ := NewLogger("DEBUG", buff, "PREFIX")

al, _ := NewAnnotatedLogger(bl, "Mortadelo")
al.Info("A", "B", "C")

s := buff.String()
if !strings.Contains(s, "A B C Mortadelo") {
t.Errorf("missing suffix: %s", s)
}
}

func TestWrappedAnnotatedLogger(t *testing.T) {
buff := bytes.NewBuffer(make([]byte, 1024))
bl, _ := NewLogger("DEBUG", buff, "PREFIX")

al, _ := NewAnnotatedLogger(bl, "Mortadelo")
al, _ = NewAnnotatedLogger(al, "Filemon")
al.Warning("B", "C", "D")

s := buff.String()
if !strings.Contains(s, "B C D Mortadelo Filemon") {
t.Errorf("missing suffix: %s", s)
}
}
39 changes: 21 additions & 18 deletions proxy/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
package proxy

import (
"fmt"

"github.com/luraproject/lura/v2/config"
"github.com/luraproject/lura/v2/logging"
"github.com/luraproject/lura/v2/sd"
Expand Down Expand Up @@ -56,47 +58,48 @@ type defaultFactory struct {

// New implements the Factory interface
func (pf defaultFactory) New(cfg *config.EndpointConfig) (p Proxy, err error) {
l, _ := logging.NewAnnotatedLogger(pf.logger, fmt.Sprintf("%s %s", cfg.Method, cfg.Endpoint))
switch len(cfg.Backend) {
case 0:
err = ErrNoBackends
case 1:
p, err = pf.newSingle(cfg)
p, err = pf.newSingle(l, cfg)
default:
p, err = pf.newMulti(cfg)
p, err = pf.newMulti(l, cfg)
}
if err != nil {
return
}

p = NewPluginMiddleware(pf.logger, cfg)(p)
p = NewStaticMiddleware(pf.logger, cfg)(p)
p = NewPluginMiddleware(l, cfg)(p)
p = NewStaticMiddleware(l, cfg)(p)
return
}

func (pf defaultFactory) newMulti(cfg *config.EndpointConfig) (p Proxy, err error) {
func (pf defaultFactory) newMulti(l logging.Logger, cfg *config.EndpointConfig) (p Proxy, err error) {
backendProxy := make([]Proxy, len(cfg.Backend))
for i, backend := range cfg.Backend {
backendProxy[i] = pf.newStack(backend)
backendProxy[i] = pf.newStack(l, backend)
}
p = NewMergeDataMiddleware(pf.logger, cfg)(backendProxy...)
p = NewFlatmapMiddleware(pf.logger, cfg)(p)
p = NewMergeDataMiddleware(l, cfg)(backendProxy...)
p = NewFlatmapMiddleware(l, cfg)(p)
return
}

func (pf defaultFactory) newSingle(cfg *config.EndpointConfig) (Proxy, error) {
return pf.newStack(cfg.Backend[0]), nil
func (pf defaultFactory) newSingle(l logging.Logger, cfg *config.EndpointConfig) (Proxy, error) {
return pf.newStack(l, cfg.Backend[0]), nil
}

func (pf defaultFactory) newStack(backend *config.Backend) (p Proxy) {
func (pf defaultFactory) newStack(l logging.Logger, backend *config.Backend) (p Proxy) {
p = pf.backendFactory(backend)
p = NewBackendPluginMiddleware(pf.logger, backend)(p)
p = NewGraphQLMiddleware(pf.logger, backend)(p)
p = NewFilterHeadersMiddleware(pf.logger, backend)(p)
p = NewFilterQueryStringsMiddleware(pf.logger, backend)(p)
p = NewLoadBalancedMiddlewareWithSubscriberAndLogger(pf.logger, pf.subscriberFactory(backend))(p)
p = NewBackendPluginMiddleware(l, backend)(p)
p = NewGraphQLMiddleware(l, backend)(p)
p = NewFilterHeadersMiddleware(l, backend)(p)
p = NewFilterQueryStringsMiddleware(l, backend)(p)
p = NewLoadBalancedMiddlewareWithSubscriberAndLogger(l, pf.subscriberFactory(backend))(p)
if backend.ConcurrentCalls > 1 {
p = NewConcurrentMiddlewareWithLogger(pf.logger, backend)(p)
p = NewConcurrentMiddlewareWithLogger(l, backend)(p)
}
p = NewRequestBuilderMiddlewareWithLogger(pf.logger, backend)(p)
p = NewRequestBuilderMiddlewareWithLogger(l, backend)(p)
return
}