Skip to content

Remove verbose flag #400

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Aug 29, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/bug-report.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ assignees: ''

### Stack Trace

[If applicable, the stack trace which shows the error. Find it with `cortex logs -v <resource name>`, or use `kubectl get pods -n cortex` and use the name of the failed pod in `kubectl logs <pod name> -n cortex`]
[If applicable, the stack trace which shows the error. Find it with `cortex logs <resource name>`, or use `kubectl get pods -n cortex` and use the name of the failed pod in `kubectl logs <pod name> -n cortex`]

```
<paste stack trace here>
Expand Down
4 changes: 1 addition & 3 deletions cli/cmd/lib_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import (
"os"
"os/signal"
"regexp"
"strconv"
"strings"
"time"

Expand Down Expand Up @@ -153,7 +152,7 @@ func HTTPUploadZip(endpoint string, zipInput *zip.Input, fileName string, qParam
return HTTPUpload(endpoint, uploadInput, qParams...)
}

func StreamLogs(appName string, resourceName string, resourceType string, verbose bool) error {
func StreamLogs(appName string, resourceName string, resourceType string) error {
interrupt := make(chan os.Signal, 1)
signal.Notify(interrupt, os.Interrupt)

Expand All @@ -166,7 +165,6 @@ func StreamLogs(appName string, resourceName string, resourceType string, verbos
values.Set("resourceName", resourceName)
values.Set("resourceType", resourceType)
values.Set("appName", appName)
values.Set("verbose", strconv.FormatBool(verbose))
req.URL.RawQuery = values.Encode()
wsURL := req.URL.String()
wsURL = strings.Replace(wsURL, "http", "ws", 1)
Expand Down
3 changes: 1 addition & 2 deletions cli/cmd/logs.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import (
func init() {
addAppNameFlag(logsCmd)
addEnvFlag(logsCmd)
addVerboseFlag(logsCmd)
// addResourceTypesToHelp(logsCmd)
}

Expand Down Expand Up @@ -59,7 +58,7 @@ var logsCmd = &cobra.Command{
errors.Exit(err)
}

err = StreamLogs(appName, resourceName, resourceTypeStr, flagVerbose)
err = StreamLogs(appName, resourceName, resourceTypeStr)
if err != nil {
errors.Exit(err)
}
Expand Down
3 changes: 1 addition & 2 deletions docs/cluster/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,9 @@ Flags:
-d, --deployment string deployment name
-e, --env string environment (default "dev")
-h, --help help for logs
-v, --verbose show verbose output
```

The `logs` command streams logs from the workload corresponding to the specified resource. For example, `cortex logs api my-api` will stream the logs from the most recent api named `my-api`. `RESOURCE_TYPE` is optional (unless there are name colisions), so `cortex logs my-api` will also work. Using the `-v` or `--verbose` flag will show all of the logs for the workload (not just Cortex's logs).
The `logs` command streams logs from the workload corresponding to the specified resource. For example, `cortex logs api my-api` will stream the logs from the most recent api named `my-api`. `RESOURCE_TYPE` is optional (unless there are name colisions), so `cortex logs my-api` will also work.

## refresh

Expand Down
2 changes: 1 addition & 1 deletion docs/deployments/request-handlers.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,4 +102,4 @@ def pre_inference(sample, metadata):
...
```

The output of these logs can be viewed using `cortex logs -v <api_name>`.
The output of these logs can be viewed using `cortex logs <api_name>`.
2 changes: 1 addition & 1 deletion docs/deployments/statuses.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
| creating | API is being created |
| stopping | API is stopping |
| stopped | API is stopped |
| error | API was not created due to an error; run `cortex logs -v <name>` to view the logs |
| error | API was not created due to an error; run `cortex logs <name>` to view the logs |
| skipped | API was not created due to an error in another resource |
| upstream error | API was not created due to an error in one of its dependencies; a previous version of this API may be ready |
| upstream termination | API was not created because one of its dependencies was terminated; a previous version of this API may be ready |
Expand Down
16 changes: 7 additions & 9 deletions pkg/operator/endpoints/logs.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@ func ReadLogs(w http.ResponseWriter, r *http.Request) {
return
}

verbose := getOptionalBoolQParam("verbose", false, r)

workloadID := getOptionalQParam("workloadID", r)
resourceID := getOptionalQParam("resourceID", r)
resourceName := getOptionalQParam("resourceName", r)
Expand All @@ -54,7 +52,7 @@ func ReadLogs(w http.ResponseWriter, r *http.Request) {

if workloadID != "" {
podLabels["workloadID"] = workloadID
readLogs(w, r, podLabels, appName, verbose)
readLogs(w, r, podLabels, appName)
return
}

Expand All @@ -70,7 +68,7 @@ func ReadLogs(w http.ResponseWriter, r *http.Request) {
}

podLabels["workloadID"] = workloadID
readLogs(w, r, podLabels, appName, verbose)
readLogs(w, r, podLabels, appName)
return
}

Expand All @@ -90,7 +88,7 @@ func ReadLogs(w http.ResponseWriter, r *http.Request) {
} else {
podLabels["workloadID"] = res.GetWorkloadID()
}
readLogs(w, r, podLabels, appName, verbose)
readLogs(w, r, podLabels, appName)
return
}

Expand All @@ -103,7 +101,7 @@ func ReadLogs(w http.ResponseWriter, r *http.Request) {
} else {
podLabels["workloadID"] = res.GetWorkloadID()
}
readLogs(w, r, podLabels, appName, verbose)
readLogs(w, r, podLabels, appName)
return
}

Expand All @@ -115,15 +113,15 @@ func ReadLogs(w http.ResponseWriter, r *http.Request) {
workloadIDs = slices.UniqueStrings(workloadIDs)
if len(workloadIDs) == 1 {
podLabels["workloadID"] = workloadIDs[0]
readLogs(w, r, podLabels, appName, verbose)
readLogs(w, r, podLabels, appName)
return
}

RespondError(w, err)
return
}

func readLogs(w http.ResponseWriter, r *http.Request, podLabels map[string]string, appName string, verbose bool) {
func readLogs(w http.ResponseWriter, r *http.Request, podLabels map[string]string, appName string) {
upgrader := websocket.Upgrader{}
socket, err := upgrader.Upgrade(w, r, nil)
if err != nil {
Expand All @@ -132,5 +130,5 @@ func readLogs(w http.ResponseWriter, r *http.Request, podLabels map[string]strin
}
defer socket.Close()

workloads.ReadLogs(appName, podLabels, verbose, socket)
workloads.ReadLogs(appName, podLabels, socket)
}
82 changes: 19 additions & 63 deletions pkg/operator/workloads/logs.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import (
"fmt"
"io"
"os"
"regexp"
"sort"
"strings"
"time"
Expand All @@ -48,7 +47,7 @@ const (
initLogTailLines = 100
)

func ReadLogs(appName string, podSearchLabels map[string]string, verbose bool, socket *websocket.Conn) {
func ReadLogs(appName string, podSearchLabels map[string]string, socket *websocket.Conn) {
wrotePending := false

for true {
Expand All @@ -75,26 +74,26 @@ func ReadLogs(appName string, podSearchLabels map[string]string, verbose bool, s

switch {
case len(podMap[k8s.PodStatusSucceeded]) > 0:
getKubectlLogs(podMap[k8s.PodStatusSucceeded], verbose, wrotePending, socket)
getKubectlLogs(podMap[k8s.PodStatusSucceeded], wrotePending, socket)
case len(podMap[k8s.PodStatusRunning]) > 0:
getKubectlLogs(podMap[k8s.PodStatusRunning], verbose, wrotePending, socket)
getKubectlLogs(podMap[k8s.PodStatusRunning], wrotePending, socket)
case len(podMap[k8s.PodStatusPending]) > 0:
getKubectlLogs(podMap[k8s.PodStatusPending], verbose, wrotePending, socket)
getKubectlLogs(podMap[k8s.PodStatusPending], wrotePending, socket)
case len(podMap[k8s.PodStatusKilled]) > 0:
getKubectlLogs(podMap[k8s.PodStatusKilled], verbose, wrotePending, socket)
getKubectlLogs(podMap[k8s.PodStatusKilled], wrotePending, socket)
case len(podMap[k8s.PodStatusKilledOOM]) > 0:
getKubectlLogs(podMap[k8s.PodStatusKilledOOM], verbose, wrotePending, socket)
getKubectlLogs(podMap[k8s.PodStatusKilledOOM], wrotePending, socket)
case len(podMap[k8s.PodStatusFailed]) > 0:
getKubectlLogs(podMap[k8s.PodStatusFailed], verbose, wrotePending, socket)
getKubectlLogs(podMap[k8s.PodStatusFailed], wrotePending, socket)
case len(podMap[k8s.PodStatusTerminating]) > 0:
getKubectlLogs(podMap[k8s.PodStatusTerminating], verbose, wrotePending, socket)
getKubectlLogs(podMap[k8s.PodStatusTerminating], wrotePending, socket)
case len(podMap[k8s.PodStatusUnknown]) > 0:
getKubectlLogs(podMap[k8s.PodStatusUnknown], verbose, wrotePending, socket)
getKubectlLogs(podMap[k8s.PodStatusUnknown], wrotePending, socket)
default: // unexpected
if len(pods) > maxParallelPodLogging {
pods = pods[:maxParallelPodLogging]
}
getKubectlLogs(pods, verbose, wrotePending, socket)
getKubectlLogs(pods, wrotePending, socket)
}
return
}
Expand All @@ -108,7 +107,7 @@ func ReadLogs(appName string, podSearchLabels map[string]string, verbose bool, s
}

if isEnded {
getCloudWatchLogs(workloadID, verbose, socket)
getCloudWatchLogs(workloadID, socket)
return
}
}
Expand All @@ -124,7 +123,7 @@ func ReadLogs(appName string, podSearchLabels map[string]string, verbose bool, s
}
}

func getKubectlLogs(pods []kcore.Pod, verbose bool, wrotePending bool, socket *websocket.Conn) {
func getKubectlLogs(pods []kcore.Pod, wrotePending bool, socket *websocket.Conn) {
if !wrotePending {
isAllPending := true
for _, pod := range pods {
Expand Down Expand Up @@ -152,7 +151,7 @@ func getKubectlLogs(pods []kcore.Pod, verbose bool, wrotePending bool, socket *w
podCheckCancel := make(chan struct{})
defer close(podCheckCancel)

go podCheck(podCheckCancel, socket, pods, verbose, wrotePending, inr)
go podCheck(podCheckCancel, socket, pods, wrotePending, inr)
pumpStdin(socket, inw)
podCheckCancel <- struct{}{}
}
Expand Down Expand Up @@ -221,7 +220,7 @@ func createKubectlProcess(logKey LogKey, attrs *os.ProcAttr) (*os.Process, error
return process, nil
}

func podCheck(podCheckCancel chan struct{}, socket *websocket.Conn, initialPodList []kcore.Pod, verbose bool, wrotePending bool, inr *os.File) {
func podCheck(podCheckCancel chan struct{}, socket *websocket.Conn, initialPodList []kcore.Pod, wrotePending bool, inr *os.File) {
timer := time.NewTimer(0)
defer timer.Stop()

Expand Down Expand Up @@ -250,7 +249,7 @@ func podCheck(podCheckCancel chan struct{}, socket *websocket.Conn, initialPodLi
socketWriterError := make(chan error, 1)
defer close(socketWriterError)

go pumpStdout(socket, socketWriterError, outr, verbose, true)
go pumpStdout(socket, socketWriterError, outr)

for {
select {
Expand Down Expand Up @@ -337,7 +336,7 @@ func deleteProcesses(processMap map[string]*os.Process) {
}
}

func getCloudWatchLogs(prefix string, verbose bool, socket *websocket.Conn) {
func getCloudWatchLogs(prefix string, socket *websocket.Conn) {
logs, err := config.AWS.GetLogs(prefix, config.Cortex.LogGroup)
if err != nil {
config.Telemetry.ReportError(err)
Expand All @@ -355,7 +354,7 @@ func getCloudWatchLogs(prefix string, verbose bool, socket *websocket.Conn) {

socketWriterError := make(chan error)
defer close(socketWriterError)
go pumpStdout(socket, socketWriterError, logsReader, verbose, false)
go pumpStdout(socket, socketWriterError, logsReader)

inr, inw, err := os.Pipe()
if err != nil {
Expand Down Expand Up @@ -383,23 +382,17 @@ func pumpStdin(socket *websocket.Conn, writer io.Writer) {
}
}

func pumpStdout(socket *websocket.Conn, socketWriterError chan error, reader io.Reader, verbose bool, checkForLastLog bool) {
func pumpStdout(socket *websocket.Conn, socketWriterError chan error, reader io.Reader) {
scanner := bufio.NewScanner(reader)
for scanner.Scan() {
socket.SetWriteDeadline(time.Now().Add(socketWriteDeadlineWait))
logBytes := scanner.Bytes()
isLastLog := false
if !verbose {
logBytes, isLastLog = cleanLogBytes(logBytes)
}

if logBytes != nil {
if !writeSocketBytes(logBytes, socket) {
break
}
}
if isLastLog && checkForLastLog && !verbose {
break
}
}

select {
Expand All @@ -416,43 +409,6 @@ func pumpStdout(socket *websocket.Conn, socketWriterError chan error, reader io.
socket.Close()
}

// Pod name is added when streaming from kubectl logs but not for cloudwatch logs, match it if it present and filter it out
var cortexRegex = regexp.MustCompile(`^(\[[A-Za-z0-9\d\-_\s]*\]\ )?(DEBUG|INFO|WARNING|ERROR|CRITICAL):cortex:`)
var lastLogRe = regexp.MustCompile(`^workload: (\w+), completed: (\S+)`)

func extractFromCortexLog(match string, loglevel string, logStr string) (*string, bool) {
if loglevel == "DEBUG" {
return nil, false
}

cutStr := logStr[len(match):]

isLastLog := false
if lastLogRe.MatchString(cutStr) {
isLastLog = true
}

return &cutStr, isLastLog
}

func cleanLog(logStr string) (*string, bool) {
matches := cortexRegex.FindStringSubmatch(logStr)
if len(matches) == 3 {
return extractFromCortexLog(matches[0], matches[2], logStr)
}

return nil, false
}

func cleanLogBytes(logBytes []byte) ([]byte, bool) {
logStr := string(logBytes)
cleanLogStr, isLastLog := cleanLog(logStr)
if cleanLogStr == nil {
return nil, isLastLog
}
return []byte(*cleanLogStr), isLastLog
}

func stopProcess(process *os.Process) {
process.Signal(os.Interrupt)
time.Sleep(5 * time.Second)
Expand Down
17 changes: 3 additions & 14 deletions pkg/workloads/cortex/onnx_serve/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,15 +229,10 @@ def predict(app_name, api_name):

except CortexException as e:
e.wrap("error", "sample {}".format(i + 1))
logger.error(str(e))
logger.exception(
"An error occurred, see `cx logs -v api {}` for more details.".format(api["name"])
)
logger.exception(str(e))
return prediction_failed(str(e))
except Exception as e:
logger.exception(
"An error occurred, see `cx logs -v api {}` for more details.".format(api["name"])
)
logger.exception(str(e))
return prediction_failed(str(e))

predictions.append(result)
Expand Down Expand Up @@ -296,19 +291,13 @@ def start(args):
except CortexException as e:
e.wrap("error")
logger.error(str(e))
if api is not None:
logger.exception(
"An error occured starting the api, see `cx logs -v api {}` for more details".format(
api["name"]
)
)
sys.exit(1)

if api.get("tracker") is not None and api["tracker"].get("model_type") == "classification":
try:
local_cache["class_set"] = api_utils.get_classes(ctx, api["name"])
except Exception as e:
logger.warn("An error occurred while attempting to load classes", exc_info=True)
logger.warn("an error occurred while attempting to load classes", exc_info=True)

serve(app, listen="*:{}".format(args.port))

Expand Down
Loading