mirror of https://github.com/minio/minio.git
Add error filter to admin trace API (#7923)
This allows MinIO to have the ability to send back only error trace
This commit is contained in:
parent
559a59220e
commit
0373a1699b
|
@ -1465,6 +1465,7 @@ func (a adminAPIHandlers) SetConfigKeysHandler(w http.ResponseWriter, r *http.Re
|
|||
func (a adminAPIHandlers) TraceHandler(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := newContext(r, w, "HTTPTrace")
|
||||
trcAll := r.URL.Query().Get("all") == "true"
|
||||
trcErr := r.URL.Query().Get("err") == "true"
|
||||
|
||||
// Validate request signature.
|
||||
adminAPIErr := checkAdminRequestAuthType(ctx, r, "")
|
||||
|
@ -1487,11 +1488,15 @@ func (a adminAPIHandlers) TraceHandler(w http.ResponseWriter, r *http.Request) {
|
|||
traceCh := make(chan interface{}, 4000)
|
||||
|
||||
filter := func(entry interface{}) bool {
|
||||
trcInfo := entry.(trace.Info)
|
||||
if trcErr && isHTTPStatusOK(trcInfo.RespInfo.StatusCode) {
|
||||
return false
|
||||
}
|
||||
if trcAll {
|
||||
return true
|
||||
}
|
||||
trcInfo := entry.(trace.Info)
|
||||
return !strings.HasPrefix(trcInfo.ReqInfo.Path, minioReservedBucketPath)
|
||||
|
||||
}
|
||||
remoteHosts := getRemoteHosts(globalEndpoints)
|
||||
peers, err := getRestClients(remoteHosts)
|
||||
|
@ -1501,7 +1506,7 @@ func (a adminAPIHandlers) TraceHandler(w http.ResponseWriter, r *http.Request) {
|
|||
globalHTTPTrace.Subscribe(traceCh, doneCh, filter)
|
||||
|
||||
for _, peer := range peers {
|
||||
peer.Trace(traceCh, doneCh, trcAll)
|
||||
peer.Trace(traceCh, doneCh, trcAll, trcErr)
|
||||
}
|
||||
|
||||
enc := json.NewEncoder(w)
|
||||
|
|
|
@ -394,3 +394,20 @@ func getHostName(r *http.Request) (hostName string) {
|
|||
}
|
||||
return
|
||||
}
|
||||
|
||||
func isHTTPStatusOK(statusCode int) bool {
|
||||
// List of success status.
|
||||
var successStatus = []int{
|
||||
http.StatusOK,
|
||||
http.StatusCreated,
|
||||
http.StatusAccepted,
|
||||
http.StatusNoContent,
|
||||
http.StatusPartialContent,
|
||||
}
|
||||
for _, okstatus := range successStatus {
|
||||
if statusCode == okstatus {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -467,9 +467,10 @@ func (client *peerRESTClient) BackgroundHealStatus() (madmin.BgHealState, error)
|
|||
return state, err
|
||||
}
|
||||
|
||||
func (client *peerRESTClient) doTrace(traceCh chan interface{}, doneCh chan struct{}, trcAll bool) {
|
||||
func (client *peerRESTClient) doTrace(traceCh chan interface{}, doneCh chan struct{}, trcAll, trcErr bool) {
|
||||
values := make(url.Values)
|
||||
values.Set(peerRESTTraceAll, strconv.FormatBool(trcAll))
|
||||
values.Set(peerRESTTraceErr, strconv.FormatBool(trcErr))
|
||||
|
||||
// To cancel the REST request in case doneCh gets closed.
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
@ -507,10 +508,10 @@ func (client *peerRESTClient) doTrace(traceCh chan interface{}, doneCh chan stru
|
|||
}
|
||||
|
||||
// Trace - send http trace request to peer nodes
|
||||
func (client *peerRESTClient) Trace(traceCh chan interface{}, doneCh chan struct{}, trcAll bool) {
|
||||
func (client *peerRESTClient) Trace(traceCh chan interface{}, doneCh chan struct{}, trcAll, trcErr bool) {
|
||||
go func() {
|
||||
for {
|
||||
client.doTrace(traceCh, doneCh, trcAll)
|
||||
client.doTrace(traceCh, doneCh, trcAll, trcErr)
|
||||
select {
|
||||
case <-doneCh:
|
||||
return
|
||||
|
|
|
@ -56,4 +56,5 @@ const (
|
|||
peerRESTProfiler = "profiler"
|
||||
peerRESTDryRun = "dry-run"
|
||||
peerRESTTraceAll = "all"
|
||||
peerRESTTraceErr = "err"
|
||||
)
|
||||
|
|
|
@ -717,17 +717,23 @@ func (s *peerRESTServer) TraceHandler(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
trcAll := r.URL.Query().Get(peerRESTTraceAll) == "true"
|
||||
trcErr := r.URL.Query().Get(peerRESTTraceErr) == "true"
|
||||
|
||||
w.Header().Set(xhttp.Connection, "close")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.(http.Flusher).Flush()
|
||||
|
||||
filter := func(entry interface{}) bool {
|
||||
trcInfo := entry.(trace.Info)
|
||||
|
||||
if trcErr && isHTTPStatusOK(trcInfo.RespInfo.StatusCode) {
|
||||
return false
|
||||
}
|
||||
if trcAll {
|
||||
return true
|
||||
}
|
||||
trcInfo := entry.(trace.Info)
|
||||
return !strings.HasPrefix(trcInfo.ReqInfo.Path, minioReservedBucketPath)
|
||||
|
||||
}
|
||||
|
||||
doneCh := make(chan struct{})
|
||||
|
|
|
@ -32,7 +32,7 @@ type TraceInfo struct {
|
|||
}
|
||||
|
||||
// Trace - listen on http trace notifications.
|
||||
func (adm AdminClient) Trace(allTrace bool, doneCh <-chan struct{}) <-chan TraceInfo {
|
||||
func (adm AdminClient) Trace(allTrace, errTrace bool, doneCh <-chan struct{}) <-chan TraceInfo {
|
||||
traceInfoCh := make(chan TraceInfo)
|
||||
// Only success, start a routine to start reading line by line.
|
||||
go func(traceInfoCh chan<- TraceInfo) {
|
||||
|
@ -40,6 +40,7 @@ func (adm AdminClient) Trace(allTrace bool, doneCh <-chan struct{}) <-chan Trace
|
|||
for {
|
||||
urlValues := make(url.Values)
|
||||
urlValues.Set("all", strconv.FormatBool(allTrace))
|
||||
urlValues.Set("err", strconv.FormatBool(errTrace))
|
||||
reqData := requestData{
|
||||
relPath: "/v1/trace",
|
||||
queryValues: urlValues,
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/minio/minio/pkg/madmin"
|
||||
|
@ -40,7 +41,9 @@ func main() {
|
|||
|
||||
// Start listening on all http trace activity from all servers
|
||||
// in the minio cluster.
|
||||
traceCh := madmClnt.Trace(false, doneCh)
|
||||
allTrace := false
|
||||
errTrace := false
|
||||
traceCh := madmClnt.Trace(allTrace, errTrace, doneCh)
|
||||
for traceInfo := range traceCh {
|
||||
if traceInfo.Err != nil {
|
||||
fmt.Println(traceInfo.Err)
|
||||
|
|
Loading…
Reference in New Issue