Skip to content

Cleanup metrics statuses #475

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
Sep 18, 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
102 changes: 60 additions & 42 deletions cli/cmd/get.go
Original file line number Diff line number Diff line change
Expand Up @@ -244,18 +244,22 @@ func describeAPI(name string, resourcesRes *schema.GetResourcesResponse, flagVer
Rows: [][]interface{}{row},
}

var predictionMetrics string
var out string
apiMetrics, err := getAPIMetrics(ctx.App.Name, api.Name)
if err != nil || apiMetrics == nil {
predictionMetrics = "\nmetrics are not available yet\n"
} else {
statusTable = appendNetworkMetrics(statusTable, apiMetrics)
if api.Tracker != nil {
predictionMetrics = "\n" + predictionMetricsTable(apiMetrics, api) + "\n"
statusTable = appendNetworkMetrics(statusTable, apiMetrics) // adds blank stats when there is an error
out = "\n" + table.MustFormat(statusTable) + "\n"

var predictionMetrics string
if err != nil {
if !strings.Contains(err.Error(), "api is still initializing") {
predictionMetrics = fmt.Sprintf("\nerror fetching metrics: %s\n", err.Error())
}
}

out := "\n" + table.MustFormat(statusTable) + "\n"
if api.Tracker != nil && len(predictionMetrics) == 0 {
predictionMetrics = "\n" + predictionMetricsTable(apiMetrics, api) + "\n"
}

out += predictionMetrics

out += "\n" + console.Bold("url: ") + apiEndpoint
Expand All @@ -275,44 +279,55 @@ func describeAPI(name string, resourcesRes *schema.GetResourcesResponse, flagVer
return out, nil
}

func getAPIMetrics(appName, apiName string) (*schema.APIMetrics, error) {
func getAPIMetrics(appName, apiName string) (schema.APIMetrics, error) {
params := map[string]string{"appName": appName, "apiName": apiName}
httpResponse, err := HTTPGet("/metrics", params)
if err != nil {
return nil, err
return schema.APIMetrics{}, err
}

var apiMetrics schema.APIMetrics
err = json.Unmarshal(httpResponse, &apiMetrics)
if err != nil {
return nil, err
return schema.APIMetrics{}, err
}

return &apiMetrics, nil
return apiMetrics, nil
}

func appendNetworkMetrics(apiTable table.Table, apiMetrics *schema.APIMetrics) table.Table {
headers := []table.Header{
{Title: "avg latency", Hidden: apiMetrics.NetworkStats.Latency == nil},
{Title: "2XX", Hidden: apiMetrics.NetworkStats.Code2XX == 0},
{Title: "4XX", Hidden: apiMetrics.NetworkStats.Code4XX == 0},
{Title: "5XX", Hidden: apiMetrics.NetworkStats.Code5XX == 0},
}

latency := ""
if apiMetrics.NetworkStats.Latency != nil {
if *apiMetrics.NetworkStats.Latency < 1000 {
latency = fmt.Sprintf("%.6g ms", *apiMetrics.NetworkStats.Latency)
} else {
latency = fmt.Sprintf("%.6g s", (*apiMetrics.NetworkStats.Latency)/1000)
func appendNetworkMetrics(apiTable table.Table, apiMetrics schema.APIMetrics) table.Table {
latency := "-"
code2XX := "-"
code4XX := 0
code5XX := 0

if apiMetrics.NetworkStats != nil {
code4XX = apiMetrics.NetworkStats.Code4XX
code5XX = apiMetrics.NetworkStats.Code5XX
if apiMetrics.NetworkStats.Latency != nil {
if *apiMetrics.NetworkStats.Latency < 1000 {
latency = fmt.Sprintf("%.6g ms", *apiMetrics.NetworkStats.Latency)
} else {
latency = fmt.Sprintf("%.6g s", (*apiMetrics.NetworkStats.Latency)/1000)
}
}
if apiMetrics.NetworkStats.Code2XX != 0 {
code2XX = s.Int(apiMetrics.NetworkStats.Code2XX)
}
}

headers := []table.Header{
{Title: "avg latency"},
{Title: "2XX"},
{Title: "4XX", Hidden: code4XX == 0},
{Title: "5XX", Hidden: code5XX == 0},
}

row := []interface{}{
latency,
apiMetrics.NetworkStats.Code2XX,
apiMetrics.NetworkStats.Code4XX,
apiMetrics.NetworkStats.Code5XX,
code2XX,
code4XX,
code5XX,
}

apiTable.Headers = append(apiTable.Headers, headers...)
Expand All @@ -321,7 +336,7 @@ func appendNetworkMetrics(apiTable table.Table, apiMetrics *schema.APIMetrics) t
return apiTable
}

func predictionMetricsTable(apiMetrics *schema.APIMetrics, api *context.API) string {
func predictionMetricsTable(apiMetrics schema.APIMetrics, api *context.API) string {
if api.Tracker == nil {
return ""
}
Expand All @@ -332,20 +347,23 @@ func predictionMetricsTable(apiMetrics *schema.APIMetrics, api *context.API) str
return regressionMetricsTable(apiMetrics)
}

func regressionMetricsTable(apiMetrics *schema.APIMetrics) string {
func regressionMetricsTable(apiMetrics schema.APIMetrics) string {
minStr := "-"
if apiMetrics.RegressionStats.Min != nil {
minStr = fmt.Sprintf("%.9g", *apiMetrics.RegressionStats.Min)
}

maxStr := "-"
if apiMetrics.RegressionStats.Max != nil {
maxStr = fmt.Sprintf("%.9g", *apiMetrics.RegressionStats.Max)
}

avgStr := "-"
if apiMetrics.RegressionStats.Avg != nil {
avgStr = fmt.Sprintf("%.9g", *apiMetrics.RegressionStats.Avg)

if apiMetrics.RegressionStats != nil {
if apiMetrics.RegressionStats.Min != nil {
minStr = fmt.Sprintf("%.9g", *apiMetrics.RegressionStats.Min)
}

if apiMetrics.RegressionStats.Max != nil {
maxStr = fmt.Sprintf("%.9g", *apiMetrics.RegressionStats.Max)
}

if apiMetrics.RegressionStats.Avg != nil {
avgStr = fmt.Sprintf("%.9g", *apiMetrics.RegressionStats.Avg)
}
}

t := table.Table{
Expand All @@ -360,7 +378,7 @@ func regressionMetricsTable(apiMetrics *schema.APIMetrics) string {
return table.MustFormat(t)
}

func classificationMetricsTable(apiMetrics *schema.APIMetrics) string {
func classificationMetricsTable(apiMetrics schema.APIMetrics) string {
classList := make([]string, len(apiMetrics.ClassDistribution))

i := 0
Expand Down
12 changes: 6 additions & 6 deletions pkg/operator/workloads/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,21 +36,21 @@ import (
"github.com/cortexlabs/cortex/pkg/operator/config"
)

func GetMetrics(appName, apiName string) (*schema.APIMetrics, error) {
func GetMetrics(appName, apiName string) (schema.APIMetrics, error) {
ctx := CurrentContext(appName)
api := ctx.APIs[apiName]

apiSavedStatus, err := getAPISavedStatus(api.ID, api.WorkloadID, appName)
if err != nil {
return nil, err
return schema.APIMetrics{}, err
}

if apiSavedStatus == nil {
return nil, errors.Wrap(ErrorAPIInitializing(), api.Name)
return schema.APIMetrics{}, errors.Wrap(ErrorAPIInitializing(), api.Name)
}

if apiSavedStatus.Start == nil {
return nil, errors.Wrap(ErrorAPIInitializing(), api.Name)
return schema.APIMetrics{}, errors.Wrap(ErrorAPIInitializing(), api.Name)
}

apiStartTime := apiSavedStatus.Start.Truncate(time.Second)
Expand Down Expand Up @@ -83,12 +83,12 @@ func GetMetrics(appName, apiName string) (*schema.APIMetrics, error) {
if len(requestList) != 0 {
err = parallel.RunFirstErr(requestList...)
if err != nil {
return nil, err
return schema.APIMetrics{}, err
}
}

mergedMetrics := realTimeMetrics.Merge(batchMetrics)
return &mergedMetrics, nil
return mergedMetrics, nil
}

func getAPIMetricsFunc(ctx *context.Context, api *context.API, period int64, startTime *time.Time, endTime *time.Time, apiMetrics *schema.APIMetrics) func() error {
Expand Down