diff options
Diffstat (limited to 'pkg/metric')
-rw-r--r-- | pkg/metric/BUILD | 38 | ||||
-rw-r--r-- | pkg/metric/metric.proto | 101 | ||||
-rw-r--r-- | pkg/metric/metric_go_proto/metric.pb.go | 732 | ||||
-rw-r--r-- | pkg/metric/metric_state_autogen.go | 3 | ||||
-rw-r--r-- | pkg/metric/metric_test.go | 499 |
5 files changed, 735 insertions, 638 deletions
diff --git a/pkg/metric/BUILD b/pkg/metric/BUILD deleted file mode 100644 index c08792751..000000000 --- a/pkg/metric/BUILD +++ /dev/null @@ -1,38 +0,0 @@ -load("//tools:defs.bzl", "go_library", "go_test", "proto_library") - -package(licenses = ["notice"]) - -go_library( - name = "metric", - srcs = [ - "metric.go", - ], - visibility = ["//:sandbox"], - deps = [ - ":metric_go_proto", - "//pkg/eventchannel", - "//pkg/log", - "//pkg/sync", - "@org_golang_google_protobuf//types/known/timestamppb", - ], -) - -proto_library( - name = "metric", - srcs = ["metric.proto"], - visibility = ["//:sandbox"], - deps = [ - "@com_google_protobuf//:timestamp_proto", - ], -) - -go_test( - name = "metric_test", - srcs = ["metric_test.go"], - library = ":metric", - deps = [ - ":metric_go_proto", - "//pkg/eventchannel", - "@org_golang_google_protobuf//proto:go_default_library", - ], -) diff --git a/pkg/metric/metric.proto b/pkg/metric/metric.proto deleted file mode 100644 index d466b6904..000000000 --- a/pkg/metric/metric.proto +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright 2018 The gVisor Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -syntax = "proto3"; - -package gvisor; - -import "google/protobuf/timestamp.proto"; - -// MetricMetadata contains all of the metadata describing a single metric. -message MetricMetadata { - // name is the unique name of the metric, usually in a "directory" format - // (e.g., /foo/count). - string name = 1; - - // description is a human-readable description of the metric. - string description = 2; - - // cumulative indicates that this metric is never decremented. - bool cumulative = 3; - - // sync indicates that values from the final metric event should be - // synchronized to the backing monitoring system at exit. - // - // If sync is false, values are only sent to the monitoring system - // periodically. There is no guarantee that values will ever be received by - // the monitoring system. - bool sync = 4; - - 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; - - message Field { - string field_name = 1; - repeated string allowed_values = 2; - } - - // fields contains the metric fields. Currently a metric can have at most - // one field. - repeated Field fields = 7; -} - -// MetricRegistration contains the metadata for all metrics that will be in -// future MetricUpdates. -message MetricRegistration { - repeated MetricMetadata metrics = 1; - repeated string stages = 2; -} - -// MetricValue the value of a metric at a single point in time. -message MetricValue { - // name is the unique name of the metric, as in MetricMetadata. - string name = 1; - - // value is the value of the metric at a single point in time. The field set - // depends on the type of the metric. - oneof value { - uint64 uint64_value = 2; - } - - repeated string field_values = 4; -} - -// StageTiming represents a new stage that's been reached by the Sentry. -message StageTiming { - string stage = 1; - google.protobuf.Timestamp started = 2; - google.protobuf.Timestamp ended = 3; -} - -// MetricUpdate contains new values for multiple distinct metrics. -// -// Metrics whose values have not changed are not included. -message MetricUpdate { - repeated MetricValue metrics = 1; - // Timing information of initialization stages reached since last update. - // The first MetricUpdate will include multiple entries, since metric - // initialization happens relatively late in the Sentry startup process. - repeated StageTiming stage_timing = 2; -} diff --git a/pkg/metric/metric_go_proto/metric.pb.go b/pkg/metric/metric_go_proto/metric.pb.go new file mode 100644 index 000000000..7d327e3a0 --- /dev/null +++ b/pkg/metric/metric_go_proto/metric.pb.go @@ -0,0 +1,732 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.25.0 +// protoc v3.13.0 +// source: pkg/metric/metric.proto + +package gvisor + +import ( + proto "github.com/golang/protobuf/proto" + timestamp "github.com/golang/protobuf/ptypes/timestamp" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// This is a compile-time assertion that a sufficiently up-to-date version +// of the legacy proto package is being used. +const _ = proto.ProtoPackageIsVersion4 + +type MetricMetadata_Type int32 + +const ( + MetricMetadata_TYPE_UINT64 MetricMetadata_Type = 0 +) + +// Enum value maps for MetricMetadata_Type. +var ( + MetricMetadata_Type_name = map[int32]string{ + 0: "TYPE_UINT64", + } + MetricMetadata_Type_value = map[string]int32{ + "TYPE_UINT64": 0, + } +) + +func (x MetricMetadata_Type) Enum() *MetricMetadata_Type { + p := new(MetricMetadata_Type) + *p = x + return p +} + +func (x MetricMetadata_Type) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (MetricMetadata_Type) Descriptor() protoreflect.EnumDescriptor { + return file_pkg_metric_metric_proto_enumTypes[0].Descriptor() +} + +func (MetricMetadata_Type) Type() protoreflect.EnumType { + return &file_pkg_metric_metric_proto_enumTypes[0] +} + +func (x MetricMetadata_Type) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use MetricMetadata_Type.Descriptor instead. +func (MetricMetadata_Type) EnumDescriptor() ([]byte, []int) { + return file_pkg_metric_metric_proto_rawDescGZIP(), []int{0, 0} +} + +type MetricMetadata_Units int32 + +const ( + MetricMetadata_UNITS_NONE MetricMetadata_Units = 0 + MetricMetadata_UNITS_NANOSECONDS MetricMetadata_Units = 1 +) + +// Enum value maps for MetricMetadata_Units. +var ( + MetricMetadata_Units_name = map[int32]string{ + 0: "UNITS_NONE", + 1: "UNITS_NANOSECONDS", + } + MetricMetadata_Units_value = map[string]int32{ + "UNITS_NONE": 0, + "UNITS_NANOSECONDS": 1, + } +) + +func (x MetricMetadata_Units) Enum() *MetricMetadata_Units { + p := new(MetricMetadata_Units) + *p = x + return p +} + +func (x MetricMetadata_Units) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (MetricMetadata_Units) Descriptor() protoreflect.EnumDescriptor { + return file_pkg_metric_metric_proto_enumTypes[1].Descriptor() +} + +func (MetricMetadata_Units) Type() protoreflect.EnumType { + return &file_pkg_metric_metric_proto_enumTypes[1] +} + +func (x MetricMetadata_Units) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use MetricMetadata_Units.Descriptor instead. +func (MetricMetadata_Units) EnumDescriptor() ([]byte, []int) { + return file_pkg_metric_metric_proto_rawDescGZIP(), []int{0, 1} +} + +type MetricMetadata struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` + Cumulative bool `protobuf:"varint,3,opt,name=cumulative,proto3" json:"cumulative,omitempty"` + Sync bool `protobuf:"varint,4,opt,name=sync,proto3" json:"sync,omitempty"` + Type MetricMetadata_Type `protobuf:"varint,5,opt,name=type,proto3,enum=gvisor.MetricMetadata_Type" json:"type,omitempty"` + Units MetricMetadata_Units `protobuf:"varint,6,opt,name=units,proto3,enum=gvisor.MetricMetadata_Units" json:"units,omitempty"` + Fields []*MetricMetadata_Field `protobuf:"bytes,7,rep,name=fields,proto3" json:"fields,omitempty"` +} + +func (x *MetricMetadata) Reset() { + *x = MetricMetadata{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_metric_metric_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MetricMetadata) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MetricMetadata) ProtoMessage() {} + +func (x *MetricMetadata) ProtoReflect() protoreflect.Message { + mi := &file_pkg_metric_metric_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MetricMetadata.ProtoReflect.Descriptor instead. +func (*MetricMetadata) Descriptor() ([]byte, []int) { + return file_pkg_metric_metric_proto_rawDescGZIP(), []int{0} +} + +func (x *MetricMetadata) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *MetricMetadata) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + +func (x *MetricMetadata) GetCumulative() bool { + if x != nil { + return x.Cumulative + } + return false +} + +func (x *MetricMetadata) GetSync() bool { + if x != nil { + return x.Sync + } + return false +} + +func (x *MetricMetadata) GetType() MetricMetadata_Type { + if x != nil { + return x.Type + } + return MetricMetadata_TYPE_UINT64 +} + +func (x *MetricMetadata) GetUnits() MetricMetadata_Units { + if x != nil { + return x.Units + } + return MetricMetadata_UNITS_NONE +} + +func (x *MetricMetadata) GetFields() []*MetricMetadata_Field { + if x != nil { + return x.Fields + } + return nil +} + +type MetricRegistration struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Metrics []*MetricMetadata `protobuf:"bytes,1,rep,name=metrics,proto3" json:"metrics,omitempty"` + Stages []string `protobuf:"bytes,2,rep,name=stages,proto3" json:"stages,omitempty"` +} + +func (x *MetricRegistration) Reset() { + *x = MetricRegistration{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_metric_metric_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MetricRegistration) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MetricRegistration) ProtoMessage() {} + +func (x *MetricRegistration) ProtoReflect() protoreflect.Message { + mi := &file_pkg_metric_metric_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MetricRegistration.ProtoReflect.Descriptor instead. +func (*MetricRegistration) Descriptor() ([]byte, []int) { + return file_pkg_metric_metric_proto_rawDescGZIP(), []int{1} +} + +func (x *MetricRegistration) GetMetrics() []*MetricMetadata { + if x != nil { + return x.Metrics + } + return nil +} + +func (x *MetricRegistration) GetStages() []string { + if x != nil { + return x.Stages + } + return nil +} + +type MetricValue struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // Types that are assignable to Value: + // *MetricValue_Uint64Value + Value isMetricValue_Value `protobuf_oneof:"value"` + FieldValues []string `protobuf:"bytes,4,rep,name=field_values,json=fieldValues,proto3" json:"field_values,omitempty"` +} + +func (x *MetricValue) Reset() { + *x = MetricValue{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_metric_metric_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MetricValue) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MetricValue) ProtoMessage() {} + +func (x *MetricValue) ProtoReflect() protoreflect.Message { + mi := &file_pkg_metric_metric_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MetricValue.ProtoReflect.Descriptor instead. +func (*MetricValue) Descriptor() ([]byte, []int) { + return file_pkg_metric_metric_proto_rawDescGZIP(), []int{2} +} + +func (x *MetricValue) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (m *MetricValue) GetValue() isMetricValue_Value { + if m != nil { + return m.Value + } + return nil +} + +func (x *MetricValue) GetUint64Value() uint64 { + if x, ok := x.GetValue().(*MetricValue_Uint64Value); ok { + return x.Uint64Value + } + return 0 +} + +func (x *MetricValue) GetFieldValues() []string { + if x != nil { + return x.FieldValues + } + return nil +} + +type isMetricValue_Value interface { + isMetricValue_Value() +} + +type MetricValue_Uint64Value struct { + Uint64Value uint64 `protobuf:"varint,2,opt,name=uint64_value,json=uint64Value,proto3,oneof"` +} + +func (*MetricValue_Uint64Value) isMetricValue_Value() {} + +type StageTiming struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Stage string `protobuf:"bytes,1,opt,name=stage,proto3" json:"stage,omitempty"` + Started *timestamp.Timestamp `protobuf:"bytes,2,opt,name=started,proto3" json:"started,omitempty"` + Ended *timestamp.Timestamp `protobuf:"bytes,3,opt,name=ended,proto3" json:"ended,omitempty"` +} + +func (x *StageTiming) Reset() { + *x = StageTiming{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_metric_metric_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *StageTiming) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StageTiming) ProtoMessage() {} + +func (x *StageTiming) ProtoReflect() protoreflect.Message { + mi := &file_pkg_metric_metric_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use StageTiming.ProtoReflect.Descriptor instead. +func (*StageTiming) Descriptor() ([]byte, []int) { + return file_pkg_metric_metric_proto_rawDescGZIP(), []int{3} +} + +func (x *StageTiming) GetStage() string { + if x != nil { + return x.Stage + } + return "" +} + +func (x *StageTiming) GetStarted() *timestamp.Timestamp { + if x != nil { + return x.Started + } + return nil +} + +func (x *StageTiming) GetEnded() *timestamp.Timestamp { + if x != nil { + return x.Ended + } + return nil +} + +type MetricUpdate struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Metrics []*MetricValue `protobuf:"bytes,1,rep,name=metrics,proto3" json:"metrics,omitempty"` + StageTiming []*StageTiming `protobuf:"bytes,2,rep,name=stage_timing,json=stageTiming,proto3" json:"stage_timing,omitempty"` +} + +func (x *MetricUpdate) Reset() { + *x = MetricUpdate{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_metric_metric_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MetricUpdate) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MetricUpdate) ProtoMessage() {} + +func (x *MetricUpdate) ProtoReflect() protoreflect.Message { + mi := &file_pkg_metric_metric_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MetricUpdate.ProtoReflect.Descriptor instead. +func (*MetricUpdate) Descriptor() ([]byte, []int) { + return file_pkg_metric_metric_proto_rawDescGZIP(), []int{4} +} + +func (x *MetricUpdate) GetMetrics() []*MetricValue { + if x != nil { + return x.Metrics + } + return nil +} + +func (x *MetricUpdate) GetStageTiming() []*StageTiming { + if x != nil { + return x.StageTiming + } + return nil +} + +type MetricMetadata_Field struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + FieldName string `protobuf:"bytes,1,opt,name=field_name,json=fieldName,proto3" json:"field_name,omitempty"` + AllowedValues []string `protobuf:"bytes,2,rep,name=allowed_values,json=allowedValues,proto3" json:"allowed_values,omitempty"` +} + +func (x *MetricMetadata_Field) Reset() { + *x = MetricMetadata_Field{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_metric_metric_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MetricMetadata_Field) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MetricMetadata_Field) ProtoMessage() {} + +func (x *MetricMetadata_Field) ProtoReflect() protoreflect.Message { + mi := &file_pkg_metric_metric_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MetricMetadata_Field.ProtoReflect.Descriptor instead. +func (*MetricMetadata_Field) Descriptor() ([]byte, []int) { + return file_pkg_metric_metric_proto_rawDescGZIP(), []int{0, 0} +} + +func (x *MetricMetadata_Field) GetFieldName() string { + if x != nil { + return x.FieldName + } + return "" +} + +func (x *MetricMetadata_Field) GetAllowedValues() []string { + if x != nil { + return x.AllowedValues + } + return nil +} + +var File_pkg_metric_metric_proto protoreflect.FileDescriptor + +var file_pkg_metric_metric_proto_rawDesc = []byte{ + 0x0a, 0x17, 0x70, 0x6b, 0x67, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2f, 0x6d, 0x65, 0x74, + 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x06, 0x67, 0x76, 0x69, 0x73, 0x6f, + 0x72, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x22, 0xad, 0x03, 0x0a, 0x0e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, + 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x63, + 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x0a, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x73, + 0x79, 0x6e, 0x63, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x73, 0x79, 0x6e, 0x63, 0x12, + 0x2f, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, + 0x67, 0x76, 0x69, 0x73, 0x6f, 0x72, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, + 0x12, 0x32, 0x0a, 0x05, 0x75, 0x6e, 0x69, 0x74, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x1c, 0x2e, 0x67, 0x76, 0x69, 0x73, 0x6f, 0x72, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x4d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x55, 0x6e, 0x69, 0x74, 0x73, 0x52, 0x05, 0x75, + 0x6e, 0x69, 0x74, 0x73, 0x12, 0x34, 0x0a, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x18, 0x07, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x76, 0x69, 0x73, 0x6f, 0x72, 0x2e, 0x4d, 0x65, + 0x74, 0x72, 0x69, 0x63, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x46, 0x69, 0x65, + 0x6c, 0x64, 0x52, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x1a, 0x4d, 0x0a, 0x05, 0x46, 0x69, + 0x65, 0x6c, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4e, 0x61, + 0x6d, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x5f, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x61, 0x6c, 0x6c, 0x6f, + 0x77, 0x65, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, 0x17, 0x0a, 0x04, 0x54, 0x79, 0x70, + 0x65, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x49, 0x4e, 0x54, 0x36, 0x34, + 0x10, 0x00, 0x22, 0x2e, 0x0a, 0x05, 0x55, 0x6e, 0x69, 0x74, 0x73, 0x12, 0x0e, 0x0a, 0x0a, 0x55, + 0x4e, 0x49, 0x54, 0x53, 0x5f, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x55, + 0x4e, 0x49, 0x54, 0x53, 0x5f, 0x4e, 0x41, 0x4e, 0x4f, 0x53, 0x45, 0x43, 0x4f, 0x4e, 0x44, 0x53, + 0x10, 0x01, 0x22, 0x5e, 0x0a, 0x12, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x65, 0x67, 0x69, + 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x30, 0x0a, 0x07, 0x6d, 0x65, 0x74, 0x72, + 0x69, 0x63, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x76, 0x69, 0x73, + 0x6f, 0x72, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, + 0x61, 0x52, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, + 0x61, 0x67, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x67, + 0x65, 0x73, 0x22, 0x72, 0x0a, 0x0b, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0c, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x48, 0x00, 0x52, 0x0b, 0x75, + 0x69, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x66, 0x69, + 0x65, 0x6c, 0x64, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x0b, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x42, 0x07, 0x0a, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x8b, 0x01, 0x0a, 0x0b, 0x53, 0x74, 0x61, 0x67, 0x65, + 0x54, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x12, 0x34, 0x0a, 0x07, + 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x07, 0x73, 0x74, 0x61, 0x72, 0x74, + 0x65, 0x64, 0x12, 0x30, 0x0a, 0x05, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x05, 0x65, + 0x6e, 0x64, 0x65, 0x64, 0x22, 0x75, 0x0a, 0x0c, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x12, 0x2d, 0x0a, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x67, 0x76, 0x69, 0x73, 0x6f, 0x72, 0x2e, 0x4d, + 0x65, 0x74, 0x72, 0x69, 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x07, 0x6d, 0x65, 0x74, 0x72, + 0x69, 0x63, 0x73, 0x12, 0x36, 0x0a, 0x0c, 0x73, 0x74, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x69, 0x6d, + 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x67, 0x76, 0x69, 0x73, + 0x6f, 0x72, 0x2e, 0x53, 0x74, 0x61, 0x67, 0x65, 0x54, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x52, 0x0b, + 0x73, 0x74, 0x61, 0x67, 0x65, 0x54, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x33, +} + +var ( + file_pkg_metric_metric_proto_rawDescOnce sync.Once + file_pkg_metric_metric_proto_rawDescData = file_pkg_metric_metric_proto_rawDesc +) + +func file_pkg_metric_metric_proto_rawDescGZIP() []byte { + file_pkg_metric_metric_proto_rawDescOnce.Do(func() { + file_pkg_metric_metric_proto_rawDescData = protoimpl.X.CompressGZIP(file_pkg_metric_metric_proto_rawDescData) + }) + return file_pkg_metric_metric_proto_rawDescData +} + +var file_pkg_metric_metric_proto_enumTypes = make([]protoimpl.EnumInfo, 2) +var file_pkg_metric_metric_proto_msgTypes = make([]protoimpl.MessageInfo, 6) +var file_pkg_metric_metric_proto_goTypes = []interface{}{ + (MetricMetadata_Type)(0), // 0: gvisor.MetricMetadata.Type + (MetricMetadata_Units)(0), // 1: gvisor.MetricMetadata.Units + (*MetricMetadata)(nil), // 2: gvisor.MetricMetadata + (*MetricRegistration)(nil), // 3: gvisor.MetricRegistration + (*MetricValue)(nil), // 4: gvisor.MetricValue + (*StageTiming)(nil), // 5: gvisor.StageTiming + (*MetricUpdate)(nil), // 6: gvisor.MetricUpdate + (*MetricMetadata_Field)(nil), // 7: gvisor.MetricMetadata.Field + (*timestamp.Timestamp)(nil), // 8: google.protobuf.Timestamp +} +var file_pkg_metric_metric_proto_depIdxs = []int32{ + 0, // 0: gvisor.MetricMetadata.type:type_name -> gvisor.MetricMetadata.Type + 1, // 1: gvisor.MetricMetadata.units:type_name -> gvisor.MetricMetadata.Units + 7, // 2: gvisor.MetricMetadata.fields:type_name -> gvisor.MetricMetadata.Field + 2, // 3: gvisor.MetricRegistration.metrics:type_name -> gvisor.MetricMetadata + 8, // 4: gvisor.StageTiming.started:type_name -> google.protobuf.Timestamp + 8, // 5: gvisor.StageTiming.ended:type_name -> google.protobuf.Timestamp + 4, // 6: gvisor.MetricUpdate.metrics:type_name -> gvisor.MetricValue + 5, // 7: gvisor.MetricUpdate.stage_timing:type_name -> gvisor.StageTiming + 8, // [8:8] is the sub-list for method output_type + 8, // [8:8] is the sub-list for method input_type + 8, // [8:8] is the sub-list for extension type_name + 8, // [8:8] is the sub-list for extension extendee + 0, // [0:8] is the sub-list for field type_name +} + +func init() { file_pkg_metric_metric_proto_init() } +func file_pkg_metric_metric_proto_init() { + if File_pkg_metric_metric_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_pkg_metric_metric_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MetricMetadata); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_metric_metric_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MetricRegistration); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_metric_metric_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MetricValue); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_metric_metric_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*StageTiming); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_metric_metric_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MetricUpdate); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_metric_metric_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MetricMetadata_Field); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_pkg_metric_metric_proto_msgTypes[2].OneofWrappers = []interface{}{ + (*MetricValue_Uint64Value)(nil), + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_pkg_metric_metric_proto_rawDesc, + NumEnums: 2, + NumMessages: 6, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_pkg_metric_metric_proto_goTypes, + DependencyIndexes: file_pkg_metric_metric_proto_depIdxs, + EnumInfos: file_pkg_metric_metric_proto_enumTypes, + MessageInfos: file_pkg_metric_metric_proto_msgTypes, + }.Build() + File_pkg_metric_metric_proto = out.File + file_pkg_metric_metric_proto_rawDesc = nil + file_pkg_metric_metric_proto_goTypes = nil + file_pkg_metric_metric_proto_depIdxs = nil +} diff --git a/pkg/metric/metric_state_autogen.go b/pkg/metric/metric_state_autogen.go new file mode 100644 index 000000000..36e5ed81b --- /dev/null +++ b/pkg/metric/metric_state_autogen.go @@ -0,0 +1,3 @@ +// automatically generated by stateify. + +package metric diff --git a/pkg/metric/metric_test.go b/pkg/metric/metric_test.go deleted file mode 100644 index 0654bdf07..000000000 --- a/pkg/metric/metric_test.go +++ /dev/null @@ -1,499 +0,0 @@ -// Copyright 2018 The gVisor Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package metric - -import ( - "testing" - "time" - - "google.golang.org/protobuf/proto" - "gvisor.dev/gvisor/pkg/eventchannel" - pb "gvisor.dev/gvisor/pkg/metric/metric_go_proto" -) - -// sliceEmitter implements eventchannel.Emitter by appending all messages to a -// slice. -type sliceEmitter []proto.Message - -// Emit implements eventchannel.Emitter.Emit. -func (s *sliceEmitter) Emit(msg proto.Message) (bool, error) { - *s = append(*s, msg) - return false, nil -} - -// Emit implements eventchannel.Emitter.Close. -func (s *sliceEmitter) Close() error { - return nil -} - -// Reset clears all events in s. -func (s *sliceEmitter) Reset() { - *s = nil -} - -// emitter is the eventchannel.Emitter used for all tests. Package eventchannel -// doesn't allow removing Emitters, so we must use one global emitter for all -// test cases. -var emitter sliceEmitter - -func init() { - reset() - - eventchannel.AddEmitter(&emitter) -} - -// reset clears all global state in the metric package. -func reset() { - initialized = false - allMetrics = makeMetricSet() - emitter.Reset() -} - -const ( - fooDescription = "Foo!" - barDescription = "Bar Baz" - counterDescription = "Counter" -) - -func TestInitialize(t *testing.T) { - defer reset() - - _, 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, pb.MetricMetadata_UNITS_NANOSECONDS, barDescription) - if err != nil { - t.Fatalf("NewUint64Metric got err %v want nil", err) - } - - if err := Initialize(); err != nil { - t.Fatalf("Initialize(): %s", err) - } - - if len(emitter) != 1 { - t.Fatalf("Initialize emitted %d events want 1", len(emitter)) - } - - mr, ok := emitter[0].(*pb.MetricRegistration) - if !ok { - t.Fatalf("emitter %v got %T want pb.MetricRegistration", emitter[0], emitter[0]) - } - - if len(mr.Metrics) != 2 { - t.Errorf("MetricRegistration got %d metrics want 2", len(mr.Metrics)) - } - - foundFoo := false - foundBar := false - for _, m := range mr.Metrics { - if m.Type != pb.MetricMetadata_TYPE_UINT64 { - t.Errorf("Metadata %+v Type got %v want pb.MetricMetadata_TYPE_UINT64", m, m.Type) - } - if !m.Cumulative { - t.Errorf("Metadata %+v Cumulative got false want true", m) - } - - switch m.Name { - case "/foo": - foundFoo = true - if m.Description != fooDescription { - t.Errorf("/foo %+v Description got %q want %q", m, m.Description, fooDescription) - } - 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 { - t.Errorf("/bar %+v Description got %q want %q", m, m.Description, barDescription) - } - 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) - } - } - } - - if !foundFoo { - t.Errorf("/foo not found: %+v", emitter) - } - if !foundBar { - t.Errorf("/bar not found: %+v", emitter) - } -} - -func TestDisable(t *testing.T) { - defer reset() - - _, 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, pb.MetricMetadata_UNITS_NONE, barDescription) - if err != nil { - t.Fatalf("NewUint64Metric got err %v want nil", err) - } - - if err := Disable(); err != nil { - t.Fatalf("Disable(): %s", err) - } - - if len(emitter) != 1 { - t.Fatalf("Initialize emitted %d events want 1", len(emitter)) - } - - mr, ok := emitter[0].(*pb.MetricRegistration) - if !ok { - t.Fatalf("emitter %v got %T want pb.MetricRegistration", emitter[0], emitter[0]) - } - - if len(mr.Metrics) != 0 { - t.Errorf("MetricRegistration got %d metrics want 0", len(mr.Metrics)) - } -} - -func TestEmitMetricUpdate(t *testing.T) { - defer reset() - - 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, pb.MetricMetadata_UNITS_NONE, barDescription) - if err != nil { - t.Fatalf("NewUint64Metric got err %v want nil", err) - } - - if err := Initialize(); err != nil { - t.Fatalf("Initialize(): %s", err) - } - - // Don't care about the registration metrics. - emitter.Reset() - EmitMetricUpdate() - - if len(emitter) != 1 { - t.Fatalf("EmitMetricUpdate emitted %d events want 1", len(emitter)) - } - - update, ok := emitter[0].(*pb.MetricUpdate) - if !ok { - t.Fatalf("emitter %v got %T want pb.MetricUpdate", emitter[0], emitter[0]) - } - - if len(update.Metrics) != 2 { - t.Errorf("MetricUpdate got %d metrics want 2", len(update.Metrics)) - } - - // Both are included for their initial values. - foundFoo := false - foundBar := false - for _, m := range update.Metrics { - switch m.Name { - case "/foo": - foundFoo = true - case "/bar": - foundBar = true - } - uv, ok := m.Value.(*pb.MetricValue_Uint64Value) - if !ok { - t.Errorf("%+v: value %v got %T want pb.MetricValue_Uint64Value", m, m.Value, m.Value) - continue - } - if uv.Uint64Value != 0 { - t.Errorf("%v: Value got %v want 0", m, uv.Uint64Value) - } - } - - if !foundFoo { - t.Errorf("/foo not found: %+v", emitter) - } - if !foundBar { - t.Errorf("/bar not found: %+v", emitter) - } - - // Increment foo. Only it is included in the next update. - foo.Increment() - - emitter.Reset() - EmitMetricUpdate() - - if len(emitter) != 1 { - t.Fatalf("EmitMetricUpdate emitted %d events want 1", len(emitter)) - } - - update, ok = emitter[0].(*pb.MetricUpdate) - if !ok { - t.Fatalf("emitter %v got %T want pb.MetricUpdate", emitter[0], emitter[0]) - } - - if len(update.Metrics) != 1 { - t.Errorf("MetricUpdate got %d metrics want 1", len(update.Metrics)) - } - - m := update.Metrics[0] - - if m.Name != "/foo" { - t.Errorf("Metric %+v name got %q want '/foo'", m, m.Name) - } - - uv, ok := m.Value.(*pb.MetricValue_Uint64Value) - if !ok { - t.Errorf("%+v: value %v got %T want pb.MetricValue_Uint64Value", m, m.Value, m.Value) - } - if uv.Uint64Value != 1 { - t.Errorf("%v: Value got %v want 1", m, uv.Uint64Value) - } -} - -func TestEmitMetricUpdateWithFields(t *testing.T) { - defer reset() - - field := Field{ - name: "weirdness_type", - allowedValues: []string{"weird1", "weird2"}} - - counter, err := NewUint64Metric("/weirdness", false, pb.MetricMetadata_UNITS_NONE, counterDescription, field) - if err != nil { - t.Fatalf("NewUint64Metric got err %v want nil", err) - } - - if err := Initialize(); err != nil { - t.Fatalf("Initialize(): %s", err) - } - - // Don't care about the registration metrics. - emitter.Reset() - EmitMetricUpdate() - - // For metrics with fields, we do not emit data unless the value is - // incremented. - if len(emitter) != 0 { - t.Fatalf("EmitMetricUpdate emitted %d events want 0", len(emitter)) - } - - counter.IncrementBy(4, "weird1") - counter.Increment("weird2") - - emitter.Reset() - EmitMetricUpdate() - - if len(emitter) != 1 { - t.Fatalf("EmitMetricUpdate emitted %d events want 1", len(emitter)) - } - - update, ok := emitter[0].(*pb.MetricUpdate) - if !ok { - t.Fatalf("emitter %v got %T want pb.MetricUpdate", emitter[0], emitter[0]) - } - - if len(update.Metrics) != 2 { - t.Errorf("MetricUpdate got %d metrics want 2", len(update.Metrics)) - } - - foundWeird1 := false - foundWeird2 := false - for i := 0; i < len(update.Metrics); i++ { - m := update.Metrics[i] - - if m.Name != "/weirdness" { - t.Errorf("Metric %+v name got %q want '/weirdness'", m, m.Name) - } - if len(m.FieldValues) != 1 { - t.Errorf("MetricUpdate got %d fields want 1", len(m.FieldValues)) - } - - switch m.FieldValues[0] { - case "weird1": - uv, ok := m.Value.(*pb.MetricValue_Uint64Value) - if !ok { - t.Errorf("%+v: value %v got %T want pb.MetricValue_Uint64Value", m, m.Value, m.Value) - } - if uv.Uint64Value != 4 { - t.Errorf("%v: Value got %v want 4", m, uv.Uint64Value) - } - foundWeird1 = true - case "weird2": - uv, ok := m.Value.(*pb.MetricValue_Uint64Value) - if !ok { - t.Errorf("%+v: value %v got %T want pb.MetricValue_Uint64Value", m, m.Value, m.Value) - } - if uv.Uint64Value != 1 { - t.Errorf("%v: Value got %v want 1", m, uv.Uint64Value) - } - foundWeird2 = true - } - } - - if !foundWeird1 { - t.Errorf("Field value weird1 not found: %+v", emitter) - } - if !foundWeird2 { - t.Errorf("Field value weird2 not found: %+v", emitter) - } -} - -func TestMetricUpdateStageTiming(t *testing.T) { - defer reset() - - expectedTimings := map[InitStage]struct{ min, max time.Duration }{} - measureStage := func(stage InitStage, body func()) { - stageStarted := time.Now() - endStage := StartStage(stage) - bodyStarted := time.Now() - body() - bodyEnded := time.Now() - endStage() - stageEnded := time.Now() - - expectedTimings[stage] = struct{ min, max time.Duration }{ - min: bodyEnded.Sub(bodyStarted), - max: stageEnded.Sub(stageStarted), - } - } - checkStage := func(got *pb.StageTiming, want InitStage) { - if InitStage(got.GetStage()) != want { - t.Errorf("%v: got stage %q expected %q", got, got.GetStage(), want) - } - timingBounds, found := expectedTimings[want] - if !found { - t.Fatalf("invalid init stage name %q", want) - } - started := got.Started.AsTime() - ended := got.Ended.AsTime() - duration := ended.Sub(started) - if duration < timingBounds.min { - t.Errorf("stage %v: lasted %v, expected at least %v", want, duration, timingBounds.min) - } else if duration > timingBounds.max { - t.Errorf("stage %v: lasted %v, expected no more than %v", want, duration, timingBounds.max) - } - } - - // Test that it's legit to go through stages before metric registration. - measureStage("before_first_update_1", func() { - time.Sleep(100 * time.Millisecond) - }) - measureStage("before_first_update_2", func() { - time.Sleep(100 * time.Millisecond) - }) - - fooMetric, err := NewUint64Metric("/foo", false, pb.MetricMetadata_UNITS_NONE, fooDescription) - if err != nil { - t.Fatalf("Cannot register /foo: %v", err) - } - emitter.Reset() - Initialize() - EmitMetricUpdate() - - // We should have gotten the metric registration and the first MetricUpdate. - if len(emitter) != 2 { - t.Fatalf("emitter has %d messages (%v), expected %d", len(emitter), emitter, 2) - } - - if registration, ok := emitter[0].(*pb.MetricRegistration); !ok { - t.Errorf("first message is not MetricRegistration: %T / %v", emitter[0], emitter[0]) - } else if len(registration.Stages) != len(allStages) { - t.Errorf("MetricRegistration has %d stages (%v), expected %d (%v)", len(registration.Stages), registration.Stages, len(allStages), allStages) - } else { - for i := 0; i < len(allStages); i++ { - if InitStage(registration.Stages[i]) != allStages[i] { - t.Errorf("MetricRegistration.Stages[%d]: got %q want %q", i, registration.Stages[i], allStages[i]) - } - } - } - - if firstUpdate, ok := emitter[1].(*pb.MetricUpdate); !ok { - t.Errorf("second message is not MetricUpdate: %T / %v", emitter[1], emitter[1]) - } else if len(firstUpdate.StageTiming) != 2 { - t.Errorf("MetricUpdate has %d stage timings (%v), expected %d", len(firstUpdate.StageTiming), firstUpdate.StageTiming, 2) - } else { - checkStage(firstUpdate.StageTiming[0], "before_first_update_1") - checkStage(firstUpdate.StageTiming[1], "before_first_update_2") - } - - // Ensure re-emitting doesn't cause another event to be sent. - emitter.Reset() - EmitMetricUpdate() - if len(emitter) != 0 { - t.Fatalf("EmitMetricUpdate emitted %d events want %d", len(emitter), 0) - } - - // Generate monitoring data, we should get an event with no stages. - fooMetric.Increment() - emitter.Reset() - EmitMetricUpdate() - if len(emitter) != 1 { - t.Fatalf("EmitMetricUpdate emitted %d events want %d", len(emitter), 1) - } else if update, ok := emitter[0].(*pb.MetricUpdate); !ok { - t.Errorf("message is not MetricUpdate: %T / %v", emitter[1], emitter[1]) - } else if len(update.StageTiming) != 0 { - t.Errorf("unexpected stage timing information: %v", update.StageTiming) - } - - // Now generate new stages. - measureStage("foo_stage_1", func() { - time.Sleep(100 * time.Millisecond) - }) - measureStage("foo_stage_2", func() { - time.Sleep(100 * time.Millisecond) - }) - emitter.Reset() - EmitMetricUpdate() - if len(emitter) != 1 { - t.Fatalf("EmitMetricUpdate emitted %d events want %d", len(emitter), 1) - } else if update, ok := emitter[0].(*pb.MetricUpdate); !ok { - t.Errorf("message is not MetricUpdate: %T / %v", emitter[1], emitter[1]) - } else if len(update.Metrics) != 0 { - t.Errorf("MetricUpdate has %d metric value changes (%v), expected %d", len(update.Metrics), update.Metrics, 0) - } else if len(update.StageTiming) != 2 { - t.Errorf("MetricUpdate has %d stages (%v), expected %d", len(update.StageTiming), update.StageTiming, 2) - } else { - checkStage(update.StageTiming[0], "foo_stage_1") - checkStage(update.StageTiming[1], "foo_stage_2") - } - - // Now try generating data for both metrics and stages. - fooMetric.Increment() - measureStage("last_stage_1", func() { - time.Sleep(100 * time.Millisecond) - }) - measureStage("last_stage_2", func() { - time.Sleep(100 * time.Millisecond) - }) - fooMetric.Increment() - emitter.Reset() - EmitMetricUpdate() - if len(emitter) != 1 { - t.Fatalf("EmitMetricUpdate emitted %d events want %d", len(emitter), 1) - } else if update, ok := emitter[0].(*pb.MetricUpdate); !ok { - t.Errorf("message is not MetricUpdate: %T / %v", emitter[1], emitter[1]) - } else if len(update.Metrics) != 1 { - t.Errorf("MetricUpdate has %d metric value changes (%v), expected %d", len(update.Metrics), update.Metrics, 1) - } else if len(update.StageTiming) != 2 { - t.Errorf("MetricUpdate has %d stages (%v), expected %d", len(update.StageTiming), update.StageTiming, 2) - } else { - checkStage(update.StageTiming[0], "last_stage_1") - checkStage(update.StageTiming[1], "last_stage_2") - } -} |