This repository has been archived by the owner on Jan 12, 2024. It is now read-only.
Detailed pseudocode
johnabass edited this page Jun 11, 2018
·
2 revisions
Consider central types within the github.com/Comcast/golang-money/money.v1
package:
type Span struct {
/* whatever money trace requires for a span */
}
// Result models the result fields of a span. The zero value of this struct
// indicates a successful span execution.
type Result struct {
// Code is an abstract value which is up to the span code to supply.
// It is not necessary to enforce that this is an HTTP status code.
// The translation into an HTTP status code should take place elsewhere.
Code int
// Err is just the error reported by the span
Err error
/* whatever else money trace needs for a result */
}
// Spanner is the core interface for this package. It acts as the factory for spans
// for all downstream code.
type Spanner interface {
Start(context.Context, Span) Tracker
}
// Tracker is the management interface for an active span. It can be used to create
// child spans and to mark the current span as finished.
type Tracker interface {
Spanner
// Finish concludes this span with the given result
Finish(Result)
}
Now consider types within the github.com/Comcast/golang-money/money.v1/moneyhttp
package:
// SpanDecoder is a strategy for turning server requests into spans
type SpanDecoder func(*http.Request) Span
// HTTPSpanner implements money.Spanner and is the root factory
// for HTTP spans
type HTTPSpanner struct {
sd SpanDecoder
/* other stuff */
}
func (hs *HTTPSpanner) Start(ctx context.Context, s Span) money.Tracker {
// create and return an HTTPTracker
}
func (hs *HTTPSpanner) Decorate(next http.Handler) http.Handler {
if ht == nil {
// allow DI of nil values to shut off money trace
return next
}
return http.HandlerFunc(func(response http.ResponseWriter, request *http.Request) {
span := hs.sd(request)
tracker := ht.Start(request.Context(), span)
next.ServeHTTP(
simpleResponseWriter{response},
request.WithContext(/* add tracker to the context */),
)
})
}
// New creates an HTTPSpanner based on options.
// See https://dave.cheney.net/2014/10/17/functional-options-for-friendly-apis
type New(options) *HTTPSpanner {
}
// HTTPTracker is the management type for child spans
type HTTPTracker struct {
}
// simpleResponseWriter is the core decorated http.ResponseWriter.
// DO NOT blindly implement http.Flusher, etc, as this will lie to other infrastructure
type simpleResponseWriter struct {
http.ResponseWriter
code int
}
func (rw simpleResponseWriter) WriteHeader(code int) {
if code < 1 {
rw.code = code
rw.WriteHeader(code)
}
}
The above meets the (2) basic use cases:
(1) Using spans within http.Handler code
func MyHandler(_ http.ResponseWriter, request *http.Request) {
// obtain the tracker from request.Context() if necessary
}
(2) Using spans in code that is unaware of HTTP semantics
func MyFunction(ctx context.Context) {
child := trackerFromCtx.Start(...)
defer child.Finish(Result{})
}