Save http trace to a file (#5300)

Save http trace to a file instead of displaying it onto the console.
the environment variable MINIO_HTTP_TRACE will be a filepath instead
of a boolean.

This to handle the scenario where both json and http tracing are
turned on. In that case, both http trace and json output are displayed
on the screen making the json not parsable. Loging this trace onto
a file helps us avoid that scenario.

Fixes #5263
This commit is contained in:
kannappanr 2018-01-05 11:24:31 -08:00 committed by GitHub
parent de2ce5acb4
commit 1de3bd6911
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 38 additions and 8 deletions

View File

@ -102,7 +102,12 @@ func handleCommonEnvVars() {
globalIsBrowserEnabled = bool(browserFlag)
}
globalHTTPTrace = os.Getenv("MINIO_HTTP_TRACE") != ""
traceFile := os.Getenv("MINIO_HTTP_TRACE")
if traceFile != "" {
var err error
globalHTTPTraceFile, err = os.OpenFile(traceFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0660)
fatalIf(err, "error opening file %s", traceFile)
}
globalDomainName = os.Getenv("MINIO_DOMAIN")
if globalDomainName != "" {

View File

@ -123,8 +123,8 @@ var (
globalHTTPServerErrorCh = make(chan error)
globalOSSignalCh = make(chan os.Signal, 1)
// Enable HTTP request/response headers and body logging.
globalHTTPTrace bool
// File to log HTTP request/response headers and body.
globalHTTPTraceFile *os.File
// List of admin peers.
globalAdminPeers = adminPeers{}

View File

@ -22,7 +22,6 @@ import (
"net"
"net/http"
"net/url"
"os"
"strings"
"github.com/minio/minio/pkg/errors"
@ -251,18 +250,18 @@ func extractPostPolicyFormValues(form *multipart.Form) (filePart io.ReadCloser,
// Log headers and body.
func httpTraceAll(f http.HandlerFunc) http.HandlerFunc {
if !globalHTTPTrace {
if globalHTTPTraceFile == nil {
return f
}
return httptracer.TraceReqHandlerFunc(f, os.Stdout, true)
return httptracer.TraceReqHandlerFunc(f, globalHTTPTraceFile, true)
}
// Log only the headers.
func httpTraceHdrs(f http.HandlerFunc) http.HandlerFunc {
if !globalHTTPTrace {
if globalHTTPTraceFile == nil {
return f
}
return httptracer.TraceReqHandlerFunc(f, os.Stdout, false)
return httptracer.TraceReqHandlerFunc(f, globalHTTPTraceFile, false)
}
// Returns "/bucketName/objectName" for path-style or virtual-host-style requests.

View File

@ -61,6 +61,7 @@ func handleSignals() {
exit(err == nil && oerr == nil)
case osSignal := <-globalOSSignalCh:
stopHTTPTrace()
log.Printf("Exiting on signal %v\n", osSignal)
exit(stopProcess())
case signal := <-globalServiceSignalCh:
@ -71,12 +72,14 @@ func handleSignals() {
log.Println("Restarting on service signal")
err := globalHTTPServer.Shutdown()
errorIf(err, "Unable to shutdown http server")
stopHTTPTrace()
rerr := restartProcess()
errorIf(rerr, "Unable to restart the server")
exit(err == nil && rerr == nil)
case serviceStop:
log.Println("Stopping on service signal")
stopHTTPTrace()
exit(stopProcess())
}
}

View File

@ -37,6 +37,14 @@ import (
"github.com/pkg/profile"
)
// Close Http tracing file.
func stopHTTPTrace() {
if globalHTTPTraceFile != nil {
errorIf(globalHTTPTraceFile.Close(), "Unable to close httpTraceFile %s", globalHTTPTraceFile.Name())
globalHTTPTraceFile = nil
}
}
// make a copy of http.Header
func cloneHeader(h http.Header) http.Header {
h2 := make(http.Header, len(h))

View File

@ -19,8 +19,10 @@ package cmd
import (
"encoding/json"
"errors"
"io/ioutil"
"net/http"
"net/url"
"os"
"reflect"
"strings"
"testing"
@ -50,6 +52,19 @@ func TestCloneHeader(t *testing.T) {
}
}
// Tests closing http tracing file.
func TestStopHTTPTrace(t *testing.T) {
var err error
globalHTTPTraceFile, err = ioutil.TempFile("", "")
if err != nil {
defer os.Remove(globalHTTPTraceFile.Name())
stopHTTPTrace()
if globalHTTPTraceFile != nil {
t.Errorf("globalHTTPTraceFile is not nil, it is expected to be nil")
}
}
}
// Tests maximum object size.
func TestMaxObjectSize(t *testing.T) {
sizes := []struct {