Skip to content

Commit 3cbde44

Browse files
committed
Cleanup middlewares.
1 parent dff0ed4 commit 3cbde44

File tree

8 files changed

+115
-94
lines changed

8 files changed

+115
-94
lines changed

.golint_exclude

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
http/design/response.go
22
^examples/.*
33
http/codegen/testing/.*
4+
http/middleware/tracing/middleware.go

examples/cellar/cmd/cellarsvc/main.go

+2-3
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import (
1212

1313
"github.com/boltdb/bolt"
1414

15-
goa "goa.design/goa"
1615
cellar "goa.design/goa/examples/cellar"
1716
sommeliersvr "goa.design/goa/examples/cellar/gen/http/sommelier/server"
1817
storagesvr "goa.design/goa/examples/cellar/gen/http/storage/server"
@@ -38,11 +37,11 @@ func main() {
3837
// packages is very simple as well.
3938
var (
4039
logger *log.Logger
41-
adapter goa.LogAdapter
40+
adapter logging.Adapter
4241
)
4342
{
4443
logger = log.New(os.Stderr, "[cellar] ", log.Ltime)
45-
adapter = goa.AdaptStdLogger(logger)
44+
adapter = logging.Adapt(logger)
4645
}
4746

4847
// Initialize service dependencies such as databases.

http/codegen/example_server.go

+4-5
Original file line numberDiff line numberDiff line change
@@ -135,16 +135,15 @@ const mainT = `func main() {
135135
flag.Parse()
136136
137137
// Setup logger and goa log adapter. Replace logger with your own using
138-
// your log package of choice. The goa.design/logging package defines
139-
// log adapters for common log packages. Writing adapters for other log
140-
// packages is very simple as well.
138+
// your log package of choice. The goa.design/middleware/logging/...
139+
// packages define log adapters for common log packages.
141140
var (
142141
logger *log.Logger
143-
adapter goa.LogAdapter
142+
adapter logging.Adapter
144143
)
145144
{
146145
logger = log.New(os.Stderr, "[{{ .APIPkg }}] ", log.Ltime)
147-
adapter = goa.AdaptStdLogger(logger)
146+
adapter = logging.Adapt(logger)
148147
}
149148
150149
// Create the structs that implement the services.

http/middleware/debugging/middleware.go

+3-8
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,8 @@ import (
99
"net/http"
1010
"strings"
1111

12-
goa "goa.design/goa"
1312
goahttp "goa.design/goa/http"
14-
"goa.design/goa/http/middleware/tracing"
13+
"goa.design/goa/http/middleware/logging"
1514
)
1615

1716
// responseDupper tees the response to a buffer and a response writer.
@@ -23,14 +22,10 @@ type responseDupper struct {
2322

2423
// New returns a debug middleware which logs all the details about incoming
2524
// requests and outgoing responses.
26-
func New(mux goahttp.Muxer, logger goa.LogAdapter) func(http.Handler) http.Handler {
25+
func New(mux goahttp.Muxer, logger logging.Adapter) func(http.Handler) http.Handler {
2726
return func(h http.Handler) http.Handler {
2827
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
29-
requestID := tracing.ContextTraceID(r.Context())
30-
if requestID == "" {
31-
requestID = shortID()
32-
}
33-
28+
requestID := shortID()
3429
if len(r.Header) > 0 {
3530
entries := make([]interface{}, 4+2*len(r.Header))
3631
entries[0] = "id"

http/middleware/logging/adapter.go

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package logging
2+
3+
import (
4+
"bytes"
5+
"context"
6+
"fmt"
7+
"log"
8+
)
9+
10+
type (
11+
// Adapter is the logging interface used by the middleware to produce
12+
// log entries.
13+
Adapter interface {
14+
// Info logs informational messages.
15+
Info(ctx context.Context, keyvals ...interface{})
16+
// Error logs error messages.
17+
Error(ctx context.Context, keyvals ...interface{})
18+
}
19+
20+
// adapter is a thin wrapper around the stdlib logger that adapts it to
21+
// the Adapter interface.
22+
adapter struct {
23+
*log.Logger
24+
}
25+
)
26+
27+
// Adapt creates a Adapter backed by a stdlib logger.
28+
func Adapt(l *log.Logger) Adapter {
29+
return &adapter{l}
30+
}
31+
32+
func (a *adapter) Info(_ context.Context, keyvals ...interface{}) { a.log("INFO", keyvals...) }
33+
func (a *adapter) Error(_ context.Context, keyvals ...interface{}) { a.log("ERROR", keyvals...) }
34+
35+
func (a *adapter) log(lvl string, keyvals ...interface{}) {
36+
n := (len(keyvals) + 1) / 2
37+
if len(keyvals)%2 != 0 {
38+
keyvals = append(keyvals, "MISSING")
39+
}
40+
var fm bytes.Buffer
41+
fm.WriteString("[%s]")
42+
vals := make([]interface{}, n+1)
43+
vals[0] = lvl
44+
for i := 0; i < len(keyvals); i += 2 {
45+
k := keyvals[i]
46+
v := keyvals[i+1]
47+
vals[i/2+1] = v
48+
fm.WriteString(fmt.Sprintf(" %s=%%+v", k))
49+
}
50+
a.Logger.Printf(fm.String(), vals...)
51+
}

http/middleware/logging/middleware.go

+5-11
Original file line numberDiff line numberDiff line change
@@ -7,31 +7,25 @@ import (
77
"net"
88
"net/http"
99
"time"
10-
11-
"goa.design/goa"
12-
"goa.design/goa/http/middleware/tracing"
1310
)
1411

1512
// New returns a middleware that logs short messages for incoming requests and
1613
// outgoing responses.
17-
func New(logger goa.LogAdapter) func(h http.Handler) http.Handler {
14+
func New(a Adapter) func(h http.Handler) http.Handler {
1815
return func(h http.Handler) http.Handler {
1916
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
20-
reqID := tracing.ContextTraceID(r.Context())
21-
if reqID == "" {
22-
reqID = shortID()
23-
}
17+
reqID := shortID()
2418
started := time.Now()
2519

26-
logger.Info(r.Context(),
20+
a.Info(r.Context(),
2721
"id", reqID,
28-
r.Method, r.URL.String(),
22+
"req", r.Method+" "+r.URL.String(),
2923
"from", from(r))
3024

3125
rw := CaptureResponse(w)
3226
h.ServeHTTP(rw, r)
3327

34-
logger.Info(r.Context(),
28+
a.Info(r.Context(),
3529
"id", reqID,
3630
"status", rw.StatusCode,
3731
"bytes", rw.ContentLength,

http/middleware/tracing/middleware.go

+36-61
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,20 @@ import (
77
"io"
88
"net/http"
99

10-
"goa.design/goa"
10+
"goa.design/goa/http/middleware/logging"
1111
)
1212

13-
// middlewareKey is the private type used for goa middlewares to store values in
14-
// the context. It is private to avoid possible collisions with keys used by
15-
// other packages.
16-
type middlewareKey int
17-
1813
const (
19-
traceKey middlewareKey = iota + 1
20-
spanKey
21-
parentSpanKey
14+
// TraceIDKey is the request context key used to store its Trace ID if any.
15+
TraceIDKey = "TraceIDCtxKey"
16+
17+
// TraceSpanIDKey is the request context key used to store the current
18+
// trace span ID if any.
19+
TraceSpanIDKey = "TraceSpanIDCtxKey"
20+
21+
// TraceParentSpanIDKey is the request context key used to store the current
22+
// trace parent span ID if any.
23+
TraceParentSpanIDKey = "TraceParentSpanIDCtxKey"
2224
)
2325

2426
const (
@@ -45,16 +47,16 @@ type (
4547
// the middleware.
4648
Option func(*options) *options
4749

48-
// tracedDoer is a client Doer that inserts the tracing headers for
49-
// each request it makes.
50+
// tracedDoer is a client Doer that inserts the tracing headers for each
51+
// request it makes.
5052
tracedDoer struct {
5153
Doer
5254
}
5355

54-
// tracedLogger is a logger which logs the trace ID with every log
55-
// entry when one is present.
56+
// tracedLogger is a logger which logs the trace ID with every log entry
57+
// when one is present.
5658
tracedLogger struct {
57-
goa.LogAdapter
59+
logging.Adapter
5860
}
5961

6062
// options is the struct storing all the options.
@@ -185,88 +187,61 @@ func WrapDoer(ctx context.Context, doer Doer) Doer {
185187

186188
// WrapLogger returns a logger which logs the trace ID with every message if
187189
// there is one.
188-
func WrapLogger(l goa.LogAdapter) goa.LogAdapter {
190+
func WrapLogger(l logging.Adapter) logging.Adapter {
189191
return &tracedLogger{l}
190192
}
191193

192-
// ContextTraceID returns the trace ID extracted from the given context if any,
193-
// the empty string otherwise.
194-
func ContextTraceID(ctx context.Context) string {
195-
if t := ctx.Value(traceKey); t != nil {
196-
return t.(string)
197-
}
198-
return ""
199-
}
200-
201-
// ContextSpanID returns the span ID extracted from the given context if any,
202-
// the empty string otherwise.
203-
func ContextSpanID(ctx context.Context) string {
204-
if s := ctx.Value(spanKey); s != nil {
205-
return s.(string)
206-
}
207-
return ""
208-
}
209-
210-
// ContextParentSpanID returns the parent span ID extracted from the given
211-
// context if any, the empty string otherwise.
212-
func ContextParentSpanID(ctx context.Context) string {
213-
if p := ctx.Value(parentSpanKey); p != nil {
214-
return p.(string)
215-
}
216-
return ""
217-
}
218-
219194
// WithTrace returns a context containing the given trace ID.
220195
func WithTrace(ctx context.Context, traceID string) context.Context {
221-
ctx = context.WithValue(ctx, traceKey, traceID)
196+
ctx = context.WithValue(ctx, TraceIDKey, traceID)
222197
return ctx
223198
}
224199

225200
// WithSpan returns a context containing the given trace, span and parent span
226201
// IDs.
227202
func WithSpan(ctx context.Context, traceID, spanID, parentID string) context.Context {
228203
if parentID != "" {
229-
ctx = context.WithValue(ctx, parentSpanKey, parentID)
204+
ctx = context.WithValue(ctx, TraceParentSpanIDKey, parentID)
230205
}
231-
ctx = context.WithValue(ctx, traceKey, traceID)
232-
ctx = context.WithValue(ctx, spanKey, spanID)
206+
ctx = context.WithValue(ctx, TraceIDKey, traceID)
207+
ctx = context.WithValue(ctx, TraceSpanIDKey, spanID)
233208
return ctx
234209
}
235210

236211
// Do adds the tracing headers to the requests before making it.
237212
func (d *tracedDoer) Do(r *http.Request) (*http.Response, error) {
238213
var (
239-
traceID = ContextTraceID(r.Context())
240-
spanID = ContextSpanID(r.Context())
214+
traceID = r.Context().Value(TraceIDKey)
215+
spanID = r.Context().Value(TraceSpanIDKey)
241216
)
242-
if traceID != "" {
243-
r.Header.Set(TraceIDHeader, traceID)
244-
r.Header.Set(ParentSpanIDHeader, spanID)
217+
if traceID != nil {
218+
r.Header.Set(TraceIDHeader, traceID.(string))
219+
r.Header.Set(ParentSpanIDHeader, spanID.(string))
245220
}
246221

247222
return d.Doer.Do(r)
248223
}
249224

250225
// Info logs the trace ID when present then the values passed as argument.
251226
func (l *tracedLogger) Info(ctx context.Context, keyvals ...interface{}) {
252-
traceID := ContextTraceID(ctx)
253-
if traceID == "" {
254-
l.LogAdapter.Info(ctx, keyvals...)
227+
traceID := ctx.Value(TraceIDKey)
228+
if traceID == nil {
229+
l.Adapter.Info(ctx, keyvals...)
255230
return
256231
}
257-
keyvals = append([]interface{}{"trace", traceID}, keyvals...)
258-
l.LogAdapter.Info(ctx, keyvals)
232+
keyvals = append([]interface{}{"trace", traceID.(string)}, keyvals...)
233+
l.Adapter.Info(ctx, keyvals)
259234
}
260235

261236
// Error logs the trace ID when present then the values passed as argument.
262237
func (l *tracedLogger) Error(ctx context.Context, keyvals ...interface{}) {
263-
traceID := ContextTraceID(ctx)
264-
if traceID == "" {
265-
l.LogAdapter.Error(ctx, keyvals...)
238+
traceID := ctx.Value(TraceIDKey)
239+
if traceID == nil {
240+
l.Adapter.Error(ctx, keyvals...)
266241
return
267242
}
268-
keyvals = append([]interface{}{"trace", traceID}, keyvals...)
269-
l.LogAdapter.Error(ctx, keyvals)
243+
keyvals = append([]interface{}{"trace", traceID.(string)}, keyvals...)
244+
l.Adapter.Error(ctx, keyvals)
270245
}
271246

272247
// shortID produces a " unique" 6 bytes long string.

http/middleware/tracing/middleware_test.go

+13-6
Original file line numberDiff line numberDiff line change
@@ -132,8 +132,6 @@ func TestMiddleware(t *testing.T) {
132132

133133
for k, c := range cases {
134134
var (
135-
ctxTraceID, ctxSpanID, ctxParentID string
136-
137135
m = New(SamplingPercent(c.Rate), SpanIDFunc(newID), TraceIDFunc(newTraceID))
138136
h = new(testHandler)
139137
headers = make(http.Header)
@@ -149,10 +147,19 @@ func TestMiddleware(t *testing.T) {
149147

150148
m(h).ServeHTTP(httptest.NewRecorder(), req)
151149

152-
ctx := h.Context
153-
ctxTraceID = ContextTraceID(ctx)
154-
ctxSpanID = ContextSpanID(ctx)
155-
ctxParentID = ContextParentSpanID(ctx)
150+
var ctxTraceID, ctxSpanID, ctxParentID string
151+
{
152+
ctx := h.Context
153+
if traceID := ctx.Value(TraceIDKey); traceID != nil {
154+
ctxTraceID = traceID.(string)
155+
}
156+
if spanID := ctx.Value(TraceSpanIDKey); spanID != nil {
157+
ctxSpanID = spanID.(string)
158+
}
159+
if parentID := ctx.Value(TraceParentSpanIDKey); parentID != nil {
160+
ctxParentID = parentID.(string)
161+
}
162+
}
156163
if ctxTraceID != c.CtxTraceID {
157164
t.Errorf("%s: invalid TraceID, expected %v - got %v", k, c.CtxTraceID, ctxTraceID)
158165
}

0 commit comments

Comments
 (0)