Sentry metrics updates.

Sentry metrics with nanoseconds units are labeled as such, and non-cumulative
sentry metrics are supported.

PiperOrigin-RevId: 307621080
This commit is contained in:
Dave Bailey 2020-04-21 09:34:42 -07:00 committed by gVisor bot
parent 120d3b50f4
commit 7c0f3bc857
7 changed files with 58 additions and 37 deletions

View File

@ -39,16 +39,11 @@ var (
// Uint64Metric encapsulates a uint64 that represents some kind of metric to be
// monitored.
//
// All metrics must be cumulative, meaning that their values will only increase
// over time.
//
// Metrics are not saved across save/restore and thus reset to zero on restore.
//
// TODO(b/67298402): Support non-cumulative metrics.
// TODO(b/67298427): Support metric fields.
type Uint64Metric struct {
// value is the actual value of the metric. It must be accessed
// atomically.
// value is the actual value of the metric. It must be accessed atomically.
value uint64
}
@ -110,13 +105,10 @@ type customUint64Metric struct {
// Register must only be called at init and will return and error if called
// after Initialized.
//
// All metrics must be cumulative, meaning that the return values of value must
// only increase over time.
//
// Preconditions:
// * name must be globally unique.
// * Initialize/Disable have not been called.
func RegisterCustomUint64Metric(name string, sync bool, description string, value func() uint64) error {
func RegisterCustomUint64Metric(name string, cumulative, sync bool, units pb.MetricMetadata_Units, description string, value func() uint64) error {
if initialized {
return ErrInitializationDone
}
@ -129,9 +121,10 @@ func RegisterCustomUint64Metric(name string, sync bool, description string, valu
metadata: &pb.MetricMetadata{
Name: name,
Description: description,
Cumulative: true,
Cumulative: cumulative,
Sync: sync,
Type: pb.MetricMetadata_UINT64,
Type: pb.MetricMetadata_TYPE_UINT64,
Units: units,
},
value: value,
}
@ -140,24 +133,32 @@ func RegisterCustomUint64Metric(name string, sync bool, description string, valu
// MustRegisterCustomUint64Metric calls RegisterCustomUint64Metric and panics
// if it returns an error.
func MustRegisterCustomUint64Metric(name string, sync bool, description string, value func() uint64) {
if err := RegisterCustomUint64Metric(name, sync, description, value); err != nil {
func MustRegisterCustomUint64Metric(name string, cumulative, sync bool, description string, value func() uint64) {
if err := RegisterCustomUint64Metric(name, cumulative, sync, pb.MetricMetadata_UNITS_NONE, description, value); err != nil {
panic(fmt.Sprintf("Unable to register metric %q: %v", name, err))
}
}
// NewUint64Metric creates and registers a new metric with the given name.
// NewUint64Metric creates and registers a new cumulative metric with the given name.
//
// Metrics must be statically defined (i.e., at init).
func NewUint64Metric(name string, sync bool, description string) (*Uint64Metric, error) {
func NewUint64Metric(name string, sync bool, units pb.MetricMetadata_Units, description string) (*Uint64Metric, error) {
var m Uint64Metric
return &m, RegisterCustomUint64Metric(name, sync, description, m.Value)
return &m, RegisterCustomUint64Metric(name, true /* cumulative */, sync, units, description, m.Value)
}
// MustCreateNewUint64Metric calls NewUint64Metric and panics if it returns an
// error.
// MustCreateNewUint64Metric calls NewUint64Metric and panics if it returns an error.
func MustCreateNewUint64Metric(name string, sync bool, description string) *Uint64Metric {
m, err := NewUint64Metric(name, sync, description)
m, err := NewUint64Metric(name, sync, pb.MetricMetadata_UNITS_NONE, description)
if err != nil {
panic(fmt.Sprintf("Unable to create metric %q: %v", name, err))
}
return m
}
// MustCreateNewUint64NanosecondsMetric calls NewUint64Metric and panics if it returns an error.
func MustCreateNewUint64NanosecondsMetric(name string, sync bool, description string) *Uint64Metric {
m, err := NewUint64Metric(name, sync, pb.MetricMetadata_UNITS_NANOSECONDS, description)
if err != nil {
panic(fmt.Sprintf("Unable to create metric %q: %v", name, err))
}

View File

@ -36,10 +36,18 @@ message MetricMetadata {
// the monitoring system.
bool sync = 4;
enum Type { UINT64 = 0; }
enum Type { TYPE_UINT64 = 0; }
// type is the type of the metric value.
Type type = 5;
enum Units {
UNITS_NONE = 0;
UNITS_NANOSECONDS = 1;
}
// units is the units of the metric value.
Units units = 6;
}
// MetricRegistration contains the metadata for all metrics that will be in

View File

@ -66,12 +66,12 @@ const (
func TestInitialize(t *testing.T) {
defer reset()
_, err := NewUint64Metric("/foo", false, fooDescription)
_, err := NewUint64Metric("/foo", false, pb.MetricMetadata_UNITS_NONE, fooDescription)
if err != nil {
t.Fatalf("NewUint64Metric got err %v want nil", err)
}
_, err = NewUint64Metric("/bar", true, barDescription)
_, err = NewUint64Metric("/bar", true, pb.MetricMetadata_UNITS_NANOSECONDS, barDescription)
if err != nil {
t.Fatalf("NewUint64Metric got err %v want nil", err)
}
@ -94,8 +94,8 @@ func TestInitialize(t *testing.T) {
foundFoo := false
foundBar := false
for _, m := range mr.Metrics {
if m.Type != pb.MetricMetadata_UINT64 {
t.Errorf("Metadata %+v Type got %v want %v", m, m.Type, pb.MetricMetadata_UINT64)
if m.Type != pb.MetricMetadata_TYPE_UINT64 {
t.Errorf("Metadata %+v Type got %v want %v", m, m.Type, pb.MetricMetadata_TYPE_UINT64)
}
if !m.Cumulative {
t.Errorf("Metadata %+v Cumulative got false want true", m)
@ -110,6 +110,9 @@ func TestInitialize(t *testing.T) {
if m.Sync {
t.Errorf("/foo %+v Sync got true want false", m)
}
if m.Units != pb.MetricMetadata_UNITS_NONE {
t.Errorf("/foo %+v Units got %v want %v", m, m.Units, pb.MetricMetadata_UNITS_NONE)
}
case "/bar":
foundBar = true
if m.Description != barDescription {
@ -118,6 +121,9 @@ func TestInitialize(t *testing.T) {
if !m.Sync {
t.Errorf("/bar %+v Sync got true want false", m)
}
if m.Units != pb.MetricMetadata_UNITS_NANOSECONDS {
t.Errorf("/bar %+v Units got %v want %v", m, m.Units, pb.MetricMetadata_UNITS_NANOSECONDS)
}
}
}
@ -132,12 +138,12 @@ func TestInitialize(t *testing.T) {
func TestDisable(t *testing.T) {
defer reset()
_, err := NewUint64Metric("/foo", false, fooDescription)
_, err := NewUint64Metric("/foo", false, pb.MetricMetadata_UNITS_NONE, fooDescription)
if err != nil {
t.Fatalf("NewUint64Metric got err %v want nil", err)
}
_, err = NewUint64Metric("/bar", true, barDescription)
_, err = NewUint64Metric("/bar", true, pb.MetricMetadata_UNITS_NONE, barDescription)
if err != nil {
t.Fatalf("NewUint64Metric got err %v want nil", err)
}
@ -161,12 +167,12 @@ func TestDisable(t *testing.T) {
func TestEmitMetricUpdate(t *testing.T) {
defer reset()
foo, err := NewUint64Metric("/foo", false, fooDescription)
foo, err := NewUint64Metric("/foo", false, pb.MetricMetadata_UNITS_NONE, fooDescription)
if err != nil {
t.Fatalf("NewUint64Metric got err %v want nil", err)
}
_, err = NewUint64Metric("/bar", true, barDescription)
_, err = NewUint64Metric("/bar", true, pb.MetricMetadata_UNITS_NONE, barDescription)
if err != nil {
t.Fatalf("NewUint64Metric got err %v want nil", err)
}

View File

@ -44,7 +44,7 @@ var (
RecordWaitTime = false
reads = metric.MustCreateNewUint64Metric("/fs/reads", false /* sync */, "Number of file reads.")
readWait = metric.MustCreateNewUint64Metric("/fs/read_wait", false /* sync */, "Time waiting on file reads, in nanoseconds.")
readWait = metric.MustCreateNewUint64NanosecondsMetric("/fs/read_wait", false /* sync */, "Time waiting on file reads, in nanoseconds.")
)
// IncrementWait increments the given wait time metric, if enabled.

View File

@ -37,9 +37,9 @@ var (
opens9P = metric.MustCreateNewUint64Metric("/gofer/opens_9p", false /* sync */, "Number of times a 9P file was opened from a gofer.")
opensHost = metric.MustCreateNewUint64Metric("/gofer/opens_host", false /* sync */, "Number of times a host file was opened from a gofer.")
reads9P = metric.MustCreateNewUint64Metric("/gofer/reads_9p", false /* sync */, "Number of 9P file reads from a gofer.")
readWait9P = metric.MustCreateNewUint64Metric("/gofer/read_wait_9p", false /* sync */, "Time waiting on 9P file reads from a gofer, in nanoseconds.")
readWait9P = metric.MustCreateNewUint64NanosecondsMetric("/gofer/read_wait_9p", false /* sync */, "Time waiting on 9P file reads from a gofer, in nanoseconds.")
readsHost = metric.MustCreateNewUint64Metric("/gofer/reads_host", false /* sync */, "Number of host file reads from a gofer.")
readWaitHost = metric.MustCreateNewUint64Metric("/gofer/read_wait_host", false /* sync */, "Time waiting on host file reads from a gofer, in nanoseconds.")
readWaitHost = metric.MustCreateNewUint64NanosecondsMetric("/gofer/read_wait_host", false /* sync */, "Time waiting on host file reads from a gofer, in nanoseconds.")
)
// fileOperations implements fs.FileOperations for a remote file system.

View File

@ -39,7 +39,7 @@ var (
opensRO = metric.MustCreateNewUint64Metric("/in_memory_file/opens_ro", false /* sync */, "Number of times an in-memory file was opened in read-only mode.")
opensW = metric.MustCreateNewUint64Metric("/in_memory_file/opens_w", false /* sync */, "Number of times an in-memory file was opened in write mode.")
reads = metric.MustCreateNewUint64Metric("/in_memory_file/reads", false /* sync */, "Number of in-memory file reads.")
readWait = metric.MustCreateNewUint64Metric("/in_memory_file/read_wait", false /* sync */, "Time waiting on in-memory file reads, in nanoseconds.")
readWait = metric.MustCreateNewUint64NanosecondsMetric("/in_memory_file/read_wait", false /* sync */, "Time waiting on in-memory file reads, in nanoseconds.")
)
// fileInodeOperations implements fs.InodeOperations for a regular tmpfs file.

View File

@ -63,7 +63,13 @@ import (
func mustCreateMetric(name, description string) *tcpip.StatCounter {
var cm tcpip.StatCounter
metric.MustRegisterCustomUint64Metric(name, false /* sync */, description, cm.Value)
metric.MustRegisterCustomUint64Metric(name, true /* cumulative */, false /* sync */, description, cm.Value)
return &cm
}
func mustCreateGauge(name, description string) *tcpip.StatCounter {
var cm tcpip.StatCounter
metric.MustRegisterCustomUint64Metric(name, false /* cumulative */, false /* sync */, description, cm.Value)
return &cm
}
@ -151,10 +157,10 @@ var Metrics = tcpip.Stats{
TCP: tcpip.TCPStats{
ActiveConnectionOpenings: mustCreateMetric("/netstack/tcp/active_connection_openings", "Number of connections opened successfully via Connect."),
PassiveConnectionOpenings: mustCreateMetric("/netstack/tcp/passive_connection_openings", "Number of connections opened successfully via Listen."),
CurrentEstablished: mustCreateMetric("/netstack/tcp/current_established", "Number of connections in ESTABLISHED state now."),
CurrentConnected: mustCreateMetric("/netstack/tcp/current_open", "Number of connections that are in connected state."),
CurrentEstablished: mustCreateGauge("/netstack/tcp/current_established", "Number of connections in ESTABLISHED state now."),
CurrentConnected: mustCreateGauge("/netstack/tcp/current_open", "Number of connections that are in connected state."),
EstablishedResets: mustCreateMetric("/netstack/tcp/established_resets", "Number of times TCP connections have made a direct transition to the CLOSED state from either the ESTABLISHED state or the CLOSE-WAIT state"),
EstablishedClosed: mustCreateMetric("/netstack/tcp/established_closed", "number of times established TCP connections made a transition to CLOSED state."),
EstablishedClosed: mustCreateMetric("/netstack/tcp/established_closed", "Number of times established TCP connections made a transition to CLOSED state."),
EstablishedTimedout: mustCreateMetric("/netstack/tcp/established_timedout", "Number of times an established connection was reset because of keep-alive time out."),
ListenOverflowSynDrop: mustCreateMetric("/netstack/tcp/listen_overflow_syn_drop", "Number of times the listen queue overflowed and a SYN was dropped."),
ListenOverflowAckDrop: mustCreateMetric("/netstack/tcp/listen_overflow_ack_drop", "Number of times the listen queue overflowed and the final ACK in the handshake was dropped."),