Configure version and trace id
This commit is contained in:
parent
50d74f20f1
commit
e7a1116461
@ -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
2
go.mod
@ -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
2
go.sum
@ -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=
|
||||
|
31
internal/version/version.go
Normal file
31
internal/version/version.go
Normal 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
|
||||
}
|
@ -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
6
pkg/headers/header.go
Normal file
@ -0,0 +1,6 @@
|
||||
package headers
|
||||
|
||||
const (
|
||||
//ContentType ...
|
||||
ContentType = "Content-Type"
|
||||
)
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user