-
Notifications
You must be signed in to change notification settings - Fork 3.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
tenant: add endpoint with instant metrics
Previously the tenant process was serving various metrics on `/_status/vars`. This endpoint has all the available metrics and these are updated every 10 sec. Many of the metrics show a rate that is calculated over the 10 sec interval. Some of the metrics are used by the cockroach operator to monitor the CPU workload of the tenant process and use that workload for automatic scaling. The 10 sec interval however is too long and causes a slow scaling up. The reporting of high CPU utilization can take up to 20 sec (to compute a delta). To resolve this, the PR adds a new endpoint `/_status/load` that provides an instant reading of a very small subset of the normal metrics - user and system CPU time for now. By having these be instant, the client can retrieve in quick succession, consecutive snapshots and compute a precise CPU utulization. It also allows the client to control the interval between the two pulls (as opposed to having it hard coded to 10 sec). Release note: None
- Loading branch information
Showing
5 changed files
with
155 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
// Copyright 2021 The Cockroach Authors. | ||
// | ||
// Licensed as a CockroachDB Enterprise file under the Cockroach Community | ||
// License (the "License"); you may not use this file except in compliance with | ||
// the License. You may obtain a copy of the License at | ||
// | ||
// https://github.com/cockroachdb/cockroach/blob/master/licenses/CCL.txt | ||
|
||
package serverccl | ||
|
||
import ( | ||
"bufio" | ||
"context" | ||
"crypto/tls" | ||
"net/http" | ||
"os" | ||
"regexp" | ||
"strconv" | ||
"testing" | ||
|
||
"github.com/cockroachdb/cockroach/pkg/base" | ||
_ "github.com/cockroachdb/cockroach/pkg/ccl/kvccl" | ||
"github.com/cockroachdb/cockroach/pkg/roachpb" | ||
"github.com/cockroachdb/cockroach/pkg/sql/tests" | ||
"github.com/cockroachdb/cockroach/pkg/testutils/serverutils" | ||
"github.com/cockroachdb/cockroach/pkg/util/leaktest" | ||
"github.com/cockroachdb/cockroach/pkg/util/log" | ||
"github.com/elastic/gosigar" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestTenantVars(t *testing.T) { | ||
defer leaktest.AfterTest(t)() | ||
defer log.Scope(t).Close(t) | ||
|
||
ctx := context.Background() | ||
|
||
serverParams, _ := tests.CreateTestServerParams() | ||
testCluster := serverutils.StartNewTestCluster(t, 1 /* numNodes */, base.TestClusterArgs{ | ||
ServerArgs: serverParams, | ||
}) | ||
defer testCluster.Stopper().Stop(ctx) | ||
|
||
server := testCluster.Server(0 /* idx */) | ||
|
||
tenant, _ := serverutils.StartTenant(t, server, base.TestTenantArgs{ | ||
TenantID: roachpb.MakeTenantID(10 /* id */), | ||
}) | ||
|
||
url := "https://" + tenant.HTTPAddr() + "/_status/load" | ||
client := http.Client{ | ||
Transport: &http.Transport{ | ||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, | ||
}, | ||
} | ||
resp, err := client.Get(url) | ||
require.NoError(t, err) | ||
defer resp.Body.Close() | ||
require.Equal(t, 200, resp.StatusCode, | ||
"invalid non-200 status code %v from tenant", resp.StatusCode) | ||
|
||
prometheusMetricStringPattern := `^(?P<metric>\w+)(?:\{` + | ||
`(?P<labelvalues>(\w+=\".*\",)*(\w+=\".*\")?)\})?\s+(?P<value>.*)$` | ||
promethusMetricStringRE := regexp.MustCompile(prometheusMetricStringPattern) | ||
|
||
var cpuUserNS, cpuSysNS float64 | ||
scanner := bufio.NewScanner(resp.Body) | ||
for scanner.Scan() { | ||
matches := promethusMetricStringRE.FindStringSubmatch(scanner.Text()) | ||
if matches != nil { | ||
if matches[1] == "sys_cpu_user_ns" { | ||
cpuUserNS, err = strconv.ParseFloat(matches[5], 64) | ||
require.NoError(t, err) | ||
} | ||
if matches[1] == "sys_cpu_sys_ns" { | ||
cpuSysNS, err = strconv.ParseFloat(matches[5], 64) | ||
require.NoError(t, err) | ||
} | ||
} | ||
} | ||
// The values are between zero and whatever User/Sys time is observed after the get. | ||
require.Positive(t, cpuUserNS) | ||
require.Positive(t, cpuSysNS) | ||
cpuTime := gosigar.ProcTime{} | ||
require.NoError(t, cpuTime.Get(os.Getpid())) | ||
require.LessOrEqual(t, cpuUserNS, float64(cpuTime.User)*1e6) | ||
require.LessOrEqual(t, cpuSysNS, float64(cpuTime.Sys)*1e6) | ||
|
||
resp, err = client.Get(url) | ||
require.NoError(t, err) | ||
defer resp.Body.Close() | ||
require.Equal(t, 200, resp.StatusCode, | ||
"invalid non-200 status code %v from tenant", resp.StatusCode) | ||
|
||
var cpuUserNS2, cpuSysNS2 float64 | ||
scanner = bufio.NewScanner(resp.Body) | ||
for scanner.Scan() { | ||
matches := promethusMetricStringRE.FindStringSubmatch(scanner.Text()) | ||
if matches != nil { | ||
if matches[1] == "sys_cpu_user_ns" { | ||
cpuUserNS2, err = strconv.ParseFloat(matches[5], 64) | ||
require.NoError(t, err) | ||
} | ||
if matches[1] == "sys_cpu_sys_ns" { | ||
cpuSysNS2, err = strconv.ParseFloat(matches[5], 64) | ||
require.NoError(t, err) | ||
} | ||
} | ||
} | ||
require.LessOrEqual(t, float64(cpuTime.User)*1e6, cpuUserNS2) | ||
require.LessOrEqual(t, float64(cpuTime.Sys)*1e6, cpuSysNS2) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters