diff --git a/quesma/quesma/ui/asset/head.html b/quesma/quesma/ui/asset/head.html index 23bdb1ac3..7633663cf 100644 --- a/quesma/quesma/ui/asset/head.html +++ b/quesma/quesma/ui/asset/head.html @@ -480,34 +480,74 @@ background-color: #dddddd; } - #request-log-messages table, #errors table { + #request-info { + background-color: rgb(0, 0, 0); + color: white; + } + + #request-info .title { + margin-top: 0; + background-color: #333; + color: white; + padding: 0 5px; + } + + #request-info pre { + padding: 0 5px; + } + + #request-info .title-logs { + margin-top: 1em; + } + + #request-info .two-columns { + display: flex; + height: 48%; + } + + #request-info .elastic-response, #request-info .quesma-response, #request-info .query-body, #request-info .query-body-translated { + flex: 1; + overflow: auto; + } + + #request-info .query-body, #request-info .quesma-response { + background-color: rgb(221, 226, 235); + color: black; + } + + #request-info .query-body, #request-info .elastic-response { + border-right: white 5px solid; + } + + #request-info table, #errors table { border-collapse: collapse; table-layout: fixed; width: 98%; word-wrap: break-word; + margin-bottom: 1em; } - #request-log-messages th, #request-log-messages td, #errors table th, #errors table td { + #request-info th, #request-info td, #errors table th, #errors table td { border: 1px solid rgb(221, 226, 235); font-family: Courier; font-size: small; padding: 0 3px; } - #request-log-messages .time { + #request-info .time { width: 10%; } - #request-log-messages .level { + #request-info .level { width: 5%; } - #request-log-messages .message { + #request-info .message { width: 55%; white-space: pre-wrap; } - #request-log-messages .fields { + #request-info .fields { width: 28%; white-space: pre-wrap; } diff --git a/quesma/quesma/ui/console_routes.go b/quesma/quesma/ui/console_routes.go index ce3a462d7..65745b626 100644 --- a/quesma/quesma/ui/console_routes.go +++ b/quesma/quesma/ui/console_routes.go @@ -118,11 +118,6 @@ func (qmc *QuesmaManagementConsole) createRouting() *mux.Router { buf := qmc.generateReportForRequestId(vars["requestId"]) _, _ = writer.Write(buf) }) - router.PathPrefix("/log/{requestId}").HandlerFunc(func(writer http.ResponseWriter, r *http.Request) { - vars := mux.Vars(r) - buf := qmc.generateLogForRequestId(vars["requestId"]) - _, _ = writer.Write(buf) - }) router.PathPrefix("/error/{reason}").HandlerFunc(func(writer http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) buf := qmc.generateErrorForReason(vars["reason"]) diff --git a/quesma/quesma/ui/html_pages_test.go b/quesma/quesma/ui/html_pages_test.go index ae2515657..470e0e994 100644 --- a/quesma/quesma/ui/html_pages_test.go +++ b/quesma/quesma/ui/html_pages_test.go @@ -49,7 +49,7 @@ func TestHtmlPages(t *testing.T) { }) t.Run("logs got no XSS", func(t *testing.T) { - response := string(qmc.generateLogForRequestId(id)) + response := string(qmc.generateReportForRequestId(id)) assert.NotContains(t, response, xss) }) diff --git a/quesma/quesma/ui/live_tail_drilldown.go b/quesma/quesma/ui/live_tail_drilldown.go index fb589c805..f1a507a5e 100644 --- a/quesma/quesma/ui/live_tail_drilldown.go +++ b/quesma/quesma/ui/live_tail_drilldown.go @@ -5,6 +5,7 @@ import ( "fmt" "gopkg.in/yaml.v3" "mitmproxy/quesma/quesma/ui/internal/builder" + "mitmproxy/quesma/quesma/ui/internal/sqlfmt" "strings" ) @@ -13,27 +14,104 @@ func (qmc *QuesmaManagementConsole) generateReportForRequestId(requestId string) request, requestFound := qmc.debugInfoMessages[requestId] qmc.mutex.Unlock() + logMessages, optAsyncId := generateLogMessages(request.logMessages, []string{}) + buffer := newBufferWithHead() if requestFound { - buffer.Write(generateSimpleTop("Report for request UUID " + requestId)) + if optAsyncId != nil { + buffer.Write(generateSimpleTop("Report for request id " + requestId + " and async id " + *optAsyncId)) + } else { + buffer.Write(generateSimpleTop("Report for request id " + requestId)) + } } else { buffer.Write(generateSimpleTop("Report not found for request UUID " + requestId)) } - buffer.Html(`
`) + buffer.Html(`
` + "\n") + + // Show Request and SQL + if requestFound { + buffer.Html(`
` + "\n") + buffer.Html(`
` + "\n") + buffer.Html("

Original query:

\n") + buffer.Html(`
`)
+		buffer.Text(string(request.IncomingQueryBody))
+		buffer.Html("\n
") + buffer.Html(`
` + "\n") + + buffer.Html(`
` + "\n") + buffer.Html("

Translated SQL:

\n") + buffer.Html(`
`)
+		buffer.Text(sqlfmt.SqlPrettyPrint(request.QueryBodyTranslated))
+		buffer.Html("\n
") + buffer.Html(`
` + "\n") + buffer.Html(`
` + "\n") + } + + buffer.Html("\n\n") + buffer.Html(`
`) + + buffer.Html(`

`) + if requestFound && len(request.logMessages) > 0 { + buffer.Html("Logs:

\n") + buffer.Write(logMessages) + } else { + buffer.Html("No logs for this request

\n") + } - debugKeyValueSlice := []queryDebugInfoWithId{} + // Show ElasticSearch and Quesma Response if requestFound { - debugKeyValueSlice = append(debugKeyValueSlice, queryDebugInfoWithId{requestId, request}) + buffer.Html(`
` + "\n") + buffer.Html(`
` + "\n") + if len(request.QueryDebugPrimarySource.QueryResp) > 0 { + tookStr := fmt.Sprintf(" took %d ms:", request.PrimaryTook.Milliseconds()) + buffer.Html("

Elastic response").Text(tookStr).Html("

\n") + buffer.Html(`
`)
+			buffer.Text(string(request.QueryDebugPrimarySource.QueryResp))
+			buffer.Html("\n
") + } else { + buffer.Html("

No Elastic response for this request

\n") + } + buffer.Html(`
` + "\n") + + buffer.Html(`
` + "\n") + if len(request.QueryDebugSecondarySource.QueryTranslatedResults) > 0 { + tookStr := fmt.Sprintf(" took %d ms:", request.SecondaryTook.Milliseconds()) + buffer.Html("

Quesma response").Text(tookStr).Html("

\n") + buffer.Html(`
`)
+			buffer.Text(string(request.QueryDebugSecondarySource.QueryTranslatedResults))
+			buffer.Html("\n
") + } else { + buffer.Html("

No Quesma response for this request

\n") + } + buffer.Html(`
` + "\n") + buffer.Html(`
` + "\n") } - buffer.Write(generateQueries(debugKeyValueSlice, false)) + buffer.Html("\n
\n") buffer.Html("\n
\n") buffer.Html(`") - buffer.Html("\n") - buffer.Html("\n") - return buffer.Bytes() -} - -func (qmc *QuesmaManagementConsole) generateLogForRequestId(requestId string) []byte { - qmc.mutex.Lock() - request, requestFound := qmc.debugInfoMessages[requestId] - qmc.mutex.Unlock() - - logMessages, optAsyncId := generateLogMessages(request.logMessages, []string{}) - - buffer := newBufferWithHead() - if requestFound { - if optAsyncId != nil { - buffer.Write(generateSimpleTop("Log for request id " + requestId + " and async id " + *optAsyncId)) - } else { - buffer.Write(generateSimpleTop("Log for request id " + requestId)) - } - } else { - buffer.Write(generateSimpleTop("Log not found for request id " + requestId)) - } - - buffer.Html(`
`) - buffer.Html("\n\n") - buffer.Html(`
`) - - buffer.Write(logMessages) - - buffer.Html("\n
\n") - buffer.Html("\n
\n") - buffer.Html(`") buffer.Html("\n")