Configure version and trace id

This commit is contained in:
RouxAntoine 2021-03-02 00:53:22 +01:00
parent 50d74f20f1
commit e7a1116461
Signed by: antoine
GPG Key ID: 098FB66FC0475E70
7 changed files with 85 additions and 32 deletions

View File

@ -3,6 +3,7 @@ package main
import (
"context"
"flag"
"go/weather/internal/version"
"go/weather/internal/web"
"go/weather/pkg/logger"
"log"
@ -32,7 +33,7 @@ func main() {
addr := web.NewListenAddr("127.0.0.1", 8080)
defaultLogger.Sugar().Infof("Weather server is listening on %s", addr)
server := web.New(defaultLogger, addr).
server := web.New(defaultLogger, addr, version.String()).
WithTLSConfigure().
WithHandler().
WithHTTPLogging().

2
go.mod
View File

@ -6,8 +6,10 @@ require (
github.com/elastic/go-sysinfo v1.6.0 // indirect
github.com/elastic/go-windows v1.0.1 // indirect
github.com/gorilla/mux v1.8.0
github.com/hashicorp/go-version v1.2.1 // indirect
github.com/magefile/mage v1.11.0 // indirect
github.com/prometheus/procfs v0.6.0 // indirect
go.elastic.co/apm v1.11.0 // indirect
go.elastic.co/apm/module/apmzap v1.11.0 // indirect
go.elastic.co/ecszap v1.0.0
go.uber.org/multierr v1.6.0 // indirect

2
go.sum
View File

@ -18,6 +18,8 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/hashicorp/go-version v1.2.1 h1:zEfKbn2+PDgroKdiOzqiE8rsmLqU2uwi5PB5pBJ3TkI=
github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901 h1:rp+c0RAYOWj8l6qbCUTSiRLG/iKnW3K3/QfPPuSsBt4=
github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901/go.mod h1:Z86h9688Y0wesXCyonoVr47MasHilkuLMqGhRZ4Hpak=

View File

@ -0,0 +1,31 @@
package version
import (
"fmt"
version "github.com/hashicorp/go-version"
)
//Version ...
const Version = "1.0.0"
//Prerelease such as "dev" (in development), "beta", "rc1", etc.
var Prerelease = "dev"
//SemVer management
var SemVer *version.Version
func init() {
SemVer = version.Must(version.NewVersion(Version))
}
// Header is the header name used to send the current in http requests.
const Header = "Weather-Version"
// String returns the complete version string, including prerelease
func String() string {
if Prerelease != "" {
return fmt.Sprintf("%s-%s", Version, Prerelease)
}
return Version
}

View File

@ -12,6 +12,7 @@ import (
"time"
"github.com/gorilla/mux"
"go.elastic.co/apm"
"go.uber.org/zap"
)
@ -26,17 +27,22 @@ type WeatherServer struct {
router *mux.Router
wlogger *logger.WeatherLogger
subRouters map[string]*mux.Router
version string
}
//New construct new instance
func New(logger *logger.WeatherLogger, addr ListenAddr) *WeatherServer {
func New(logger *logger.WeatherLogger, addr ListenAddr, version string) *WeatherServer {
return &WeatherServer{
Server: http.Server{
Addr: addr.String(),
BaseContext: func(l net.Listener) context.Context {
customContext := context.Background()
// here configure context properties
return customContext
dt := apm.DefaultTracer
tx := dt.StartTransactionOptions("http", "request", apm.TransactionOptions{
Start: time.Now(),
})
defer tx.End()
return apm.ContextWithTransaction(context.Background(), tx)
},
WriteTimeout: 15 * time.Second,
ReadTimeout: 15 * time.Second,
@ -44,6 +50,7 @@ func New(logger *logger.WeatherLogger, addr ListenAddr) *WeatherServer {
router: mux.NewRouter(),
wlogger: logger,
subRouters: make(map[string]*mux.Router, 1),
version: version,
}
}
@ -56,7 +63,10 @@ func (ws *WeatherServer) WithHandler() *WeatherServer {
api := ws.getOrCreateSubRouterByName(apiRouterName, apiPrefix)
api.HandleFunc("/health", func(rw http.ResponseWriter, r *http.Request) {
json.NewEncoder(rw).Encode(map[string]bool{"ok": true})
json.NewEncoder(rw).Encode(map[string]interface{}{
"ok": true,
"version": ws.version,
})
})
return ws

6
pkg/headers/header.go Normal file
View File

@ -0,0 +1,6 @@
package headers
const (
//ContentType ...
ContentType = "Content-Type"
)

View File

@ -2,6 +2,7 @@ package logger
import (
"bytes"
"go/weather/pkg/headers"
"io"
"io/ioutil"
"net/http"
@ -79,50 +80,50 @@ func NewLogger(loggerName, logPath string, level zap.AtomicLevel) *WeatherLogger
//HTTPLogHandler http handler to log http request and http response
func (wl *WeatherLogger) HTTPLogHandler(next http.Handler) http.Handler {
// dt := apm.DefaultTracer
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ww := ResponseWriter{
ResponseWriter: w,
}
// span, ctx := apm.StartSpan(r.Context(), "updateRequestCount", "custom")
// defer span.End()
wl.logHTTPRequest(r)
next.ServeHTTP(&ww, r)
wl.logHTTPResponse(ww)
})
}
type readCloser struct {
io.Reader
io.Closer
}
func useTeeReader(rc io.ReadCloser, w io.Writer) io.ReadCloser {
tee := io.TeeReader(rc, w)
teeCloser := readCloser{tee, rc}
return teeCloser
}
//logHTTPRequest print request information
func (wl *WeatherLogger) logHTTPRequest(r *http.Request) {
var buf bytes.Buffer
b, err := ioutil.ReadAll(io.TeeReader(r.Body, &buf))
wl.handleError(err)
r.Body = readCloser{&buf, r.Body}
traceContextFields := apmzap.TraceContext(r.Context())
r.Body = struct {
io.Reader
io.Closer
}{&buf, r.Body}
// var buf bytes.Buffer
// var buf2 bytes.Buffer
// b, err := io.Copy(io.MultiWriter(&buf, &buf2), r.Body)
// wl.handleError(err)
// r.Body = readCloser{&buf2, r.Body}
lwith := wl.Logger.
With(apmzap.TraceContext(r.Context())...).
With([]zap.Field{
zap.String("http.request.method", r.Method),
// zap.Int64("http.request.bytes", r.Header ContentLength), // total body+header len
zap.String("http.request.mime_type", r.Header.Get(headers.ContentType)),
// zap.String(""),
// zap.String(""),
}...)
wl.Logger.With(traceContextFields...).Debug("Request",
zap.String("http.request.method", r.Method),
zap.ByteString("http.request.body.content", b),
zap.Int("http.request.body.bytes", len(b)),
// zap.Int64("http.request.bytes", r.Header ContentLength), // total body+header len
// zap.String(""),
// zap.String(""),
// zap.String(""),
)
if len(b) > 0 {
lwith.With([]zap.Field{
zap.ByteString("http.request.body.content", b),
zap.Int("http.request.body.bytes", len(b)),
}...)
}
// realy log
lwith.Debug("Request")
}
//logHTTPResponse print response information