Skip to content
This repository has been archived by the owner on Oct 26, 2022. It is now read-only.

Add summary object for metric descriptors #52

Merged
merged 2 commits into from
Aug 7, 2020
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
28 changes: 23 additions & 5 deletions cmd/mock_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import (
"syscall"

mocktrace "github.com/googleinterns/cloud-operations-api-mock/api"

"github.com/googleinterns/cloud-operations-api-mock/internal/validation"
"github.com/googleinterns/cloud-operations-api-mock/server/metric"
"github.com/googleinterns/cloud-operations-api-mock/server/trace"
"google.golang.org/genproto/googleapis/devtools/cloudtrace/v2"
Expand All @@ -43,6 +43,13 @@ var (
"If flag is set, a summary page HTML file will be generated")
)

// summaryTable wraps the summaries for both trace and metrics,
// and is used to pass data to the HTML template.
type summaryTable struct {
Spans []*cloudtrace.Span
MetricDescriptors []*validation.DescriptorStatus
}

func main() {
flag.Parse()
startStandaloneServer()
Expand All @@ -60,10 +67,13 @@ func startStandaloneServer() {
}

grpcServer := grpc.NewServer()

mockTraceServer := trace.NewMockTraceServer()
cloudtrace.RegisterTraceServiceServer(grpcServer, mockTraceServer)
mocktrace.RegisterMockTraceServiceServer(grpcServer, mockTraceServer)
monitoring.RegisterMetricServiceServer(grpcServer, metric.NewMockMetricServer())

mockMetricServer := metric.NewMockMetricServer()
monitoring.RegisterMetricServiceServer(grpcServer, mockMetricServer)

log.Printf("Listening on %s\n", lis.Addr().String())

Expand All @@ -77,7 +87,8 @@ func startStandaloneServer() {
<-sig
grpcServer.GracefulStop()
if *summary {
writeSummaryPage(mockTraceServer.ResultTable())
summaryTable := createSummaryTable(mockTraceServer.SpansSummary(), mockMetricServer.MetricDescriptorSummary())
writeSummaryPage(summaryTable)
}
finish <- true
}()
Expand All @@ -88,14 +99,21 @@ func startStandaloneServer() {
<-finish
}

func createSummaryTable(spans []*cloudtrace.Span, descriptors []*validation.DescriptorStatus) summaryTable {
return summaryTable{
Spans: spans,
MetricDescriptors: descriptors,
}
}

// writeSummaryPage creates summary.html from the results and the template HTML.
func writeSummaryPage(results []*cloudtrace.Span) {
func writeSummaryPage(table summaryTable) {
outputFile, err := os.Create("../static/summary.html")
if err != nil {
panic(err)
}
t := template.Must(template.ParseFiles("../static/summary_template.html"))
err = t.Execute(outputFile, results)
err = t.Execute(outputFile, table)
if err != nil {
panic(err)
}
Expand Down
22 changes: 19 additions & 3 deletions internal/validation/mock_metric_validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"reflect"
"regexp"
"strings"
"sync"
"time"

"github.com/golang/protobuf/ptypes"
Expand All @@ -42,11 +43,26 @@ const (
// Service name regex sourced from https://github.com/asaskevich/govalidator/blob/master/patterns.go#L33
var (
labelKeyRegex = regexp.MustCompile("[a-z][a-zA0-9_-]*")
serviceNameRegex = regexp.MustCompile(`^([a-zA-Z0-9_]{1}[a-zA-Z0-9_-]{0,62}){1}(\.[a-zA-Z0-9_]{1}[a-zA-Z0-9_-]{0,62})*[\._]?$`)
serviceNameRegex = regexp.MustCompile(`^([a-zA-Z0-9_]{1}[a-zA-Z0-9_-]{0,62}){1}(\.[a-zA-Z0-9_]{1}[a-zA-Z0-9_-]{0,62})*[._]?$`)
relativeMetricNameRegex = regexp.MustCompile("[A-Za-z0-9_/]{1,100}")
diplayNameRegex = regexp.MustCompile(`opentelemetry\/.*`)
displayNameRegex = regexp.MustCompile(`opentelemetry/.*`)
)

// MetricDescriptorStatus wraps a MetricDescriptor with the status of its creation.
// Used in the MetricDescriptor summary table.
type DescriptorStatus struct {
MetricDescriptor *metric.MetricDescriptor
Status string
}

// MetricDescriptorData is a wrapper struct for all the data that the server
// keeps with respect to metric descriptors.
type MetricDescriptorData struct {
UploadedMetricDescriptors map[string]*metric.MetricDescriptor
MetricDescriptorSummary []*DescriptorStatus
MetricDescriptorsLock sync.Mutex
}

// PreviousPoint contains information about the most recently uploaded
// point for a time series.
type PreviousPoint struct {
Expand Down Expand Up @@ -142,7 +158,7 @@ func validateLabels(labels []*lbl.LabelDescriptor) error {
}

func validateMetricDisplayName(displayName string) error {
if !diplayNameRegex.MatchString(displayName) {
if !displayNameRegex.MatchString(displayName) {
return statusInvalidDisplayName
}

Expand Down
53 changes: 37 additions & 16 deletions server/metric/mock_metric.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,21 @@ import (
// uploaded data.
type MockMetricServer struct {
monitoring.UnimplementedMetricServiceServer
uploadedMetricDescriptors map[string]*metric.MetricDescriptor
uploadedMetricDescriptorsLock sync.Mutex
uploadedPoints map[string]*validation.PreviousPoint
uploadedPointsLock sync.Mutex
metricDescriptorData *validation.MetricDescriptorData
uploadedPoints map[string]*validation.PreviousPoint
uploadedPointsLock sync.Mutex
}

// NewMockMetricServer creates a new MockMetricServer and returns a pointer to it.
func NewMockMetricServer() *MockMetricServer {
uploadedMetricDescriptors := make(map[string]*metric.MetricDescriptor)
metricDescriptorData := &validation.MetricDescriptorData{
UploadedMetricDescriptors: uploadedMetricDescriptors,
}
uploadedPoints := make(map[string]*validation.PreviousPoint)
return &MockMetricServer{
uploadedMetricDescriptors: uploadedMetricDescriptors,
uploadedPoints: uploadedPoints,
metricDescriptorData: metricDescriptorData,
uploadedPoints: uploadedPoints,
}
}

Expand Down Expand Up @@ -77,9 +79,9 @@ func (s *MockMetricServer) GetMetricDescriptor(ctx context.Context, req *monitor
return nil, err
}

s.uploadedMetricDescriptorsLock.Lock()
defer s.uploadedMetricDescriptorsLock.Unlock()
metricDescriptor, err := validation.AccessMetricDescriptor(s.uploadedMetricDescriptors, req.Name)
s.metricDescriptorData.MetricDescriptorsLock.Lock()
defer s.metricDescriptorData.MetricDescriptorsLock.Unlock()
metricDescriptor, err := validation.AccessMetricDescriptor(s.metricDescriptorData.UploadedMetricDescriptors, req.Name)
if err != nil {
return nil, err
}
Expand All @@ -92,23 +94,28 @@ func (s *MockMetricServer) GetMetricDescriptor(ctx context.Context, req *monitor
func (s *MockMetricServer) CreateMetricDescriptor(ctx context.Context, req *monitoring.CreateMetricDescriptorRequest,
) (*metric.MetricDescriptor, error) {
if err := validation.ValidateRequiredFields(req); err != nil {
addMetricDescriptorToSummary(&s.metricDescriptorData.MetricDescriptorSummary, req.MetricDescriptor, err.Error())
return nil, err
}

if err := validation.ValidateProjectName(req.Name); err != nil {
addMetricDescriptorToSummary(&s.metricDescriptorData.MetricDescriptorSummary, req.MetricDescriptor, err.Error())
return nil, err
}

if err := validation.ValidateCreateMetricDescriptor(req.MetricDescriptor); err != nil {
addMetricDescriptorToSummary(&s.metricDescriptorData.MetricDescriptorSummary, req.MetricDescriptor, err.Error())
return nil, err
}

s.uploadedMetricDescriptorsLock.Lock()
defer s.uploadedMetricDescriptorsLock.Unlock()
if err := validation.AddMetricDescriptor(s.uploadedMetricDescriptors, req.MetricDescriptor.Type, req.MetricDescriptor); err != nil {
s.metricDescriptorData.MetricDescriptorsLock.Lock()
defer s.metricDescriptorData.MetricDescriptorsLock.Unlock()
if err := validation.AddMetricDescriptor(s.metricDescriptorData.UploadedMetricDescriptors, req.MetricDescriptor.Type, req.MetricDescriptor); err != nil {
addMetricDescriptorToSummary(&s.metricDescriptorData.MetricDescriptorSummary, req.MetricDescriptor, err.Error())
return nil, err
}

addMetricDescriptorToSummary(&s.metricDescriptorData.MetricDescriptorSummary, req.MetricDescriptor, "OK")
return req.MetricDescriptor, nil
}

Expand All @@ -120,9 +127,9 @@ func (s *MockMetricServer) DeleteMetricDescriptor(ctx context.Context, req *moni
return nil, err
}

s.uploadedMetricDescriptorsLock.Lock()
defer s.uploadedMetricDescriptorsLock.Unlock()
if err := validation.RemoveMetricDescriptor(s.uploadedMetricDescriptors, req.Name); err != nil {
s.metricDescriptorData.MetricDescriptorsLock.Lock()
defer s.metricDescriptorData.MetricDescriptorsLock.Unlock()
if err := validation.RemoveMetricDescriptor(s.metricDescriptorData.UploadedMetricDescriptors, req.Name); err != nil {
return nil, err
}

Expand Down Expand Up @@ -157,7 +164,7 @@ func (s *MockMetricServer) CreateTimeSeries(ctx context.Context, req *monitoring
if err := validation.ValidateProjectName(req.Name); err != nil {
return nil, err
}
if err := validation.ValidateCreateTimeSeries(req.TimeSeries, s.uploadedMetricDescriptors, s.uploadedPoints); err != nil {
if err := validation.ValidateCreateTimeSeries(req.TimeSeries, s.metricDescriptorData.UploadedMetricDescriptors, s.uploadedPoints); err != nil {
return nil, err
}
s.uploadedPointsLock.Lock()
Expand All @@ -178,3 +185,17 @@ func (s *MockMetricServer) ListTimeSeries(ctx context.Context, req *monitoring.L
ExecutionErrors: []*status.Status{},
}, nil
}

// addMetricDescriptorToSummary adds the given metric descriptor and status to the summary.
func addMetricDescriptorToSummary(summary *[]*validation.DescriptorStatus, metricDescriptor *metric.MetricDescriptor, err string) {
metricDescriptorStatus := &validation.DescriptorStatus{
MetricDescriptor: metricDescriptor,
Status: err,
}
*summary = append(*summary, metricDescriptorStatus)
}

// MetricDescriptorSummary returns the metric descriptor data to display in the summary page.
func (s *MockMetricServer) MetricDescriptorSummary() []*validation.DescriptorStatus {
return s.metricDescriptorData.MetricDescriptorSummary
}
2 changes: 1 addition & 1 deletion server/trace/mock_trace.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,6 @@ func (s *MockTraceServer) SetOnUpload(onUpload func(ctx context.Context, spans [
s.onUpload = onUpload
}

func (s *MockTraceServer) ResultTable() []*cloudtrace.Span {
func (s *MockTraceServer) SpansSummary() []*cloudtrace.Span {
return s.spanData.SpansSummary
}
40 changes: 38 additions & 2 deletions static/summary_template.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
</head>
<body>
<div class="container-summary">

<!-- Trace table -->
<h1 style="color: #6c7ae0; text-decoration: underline;">Trace Summary</h1>
<div class="summary">
<div class="summary-head">
<table>
Expand All @@ -20,11 +23,10 @@
</thead>
</table>
</div>

<div class="summary-body">
<table>
<tbody>
{{ range $index, $span := . }}
{{ range $index, $span := .Spans }}
{{ if eq $span.Status.Message "OK" }}
<tr class="body">
{{ else }}
Expand All @@ -39,6 +41,40 @@
</table>
</div>
</div>

<!-- Metric Descriptor table -->
<h1 style="color: #6c7ae0; text-decoration: underline;">Metric Descriptors Summary</h1>
<div class="summary">
<div class="summary-head">
<table>
<thead>
<tr class="head">
<th class="cell">Metric Descriptor Name</th>
<th class="cell">Metric Descriptor Type</th>
<th class="cell">Status</th>
</tr>
</thead>
</table>
</div>

<div class="summary-body">
<table>
<tbody>
{{ range $index, $md := .MetricDescriptors }}
{{ if eq $md.Status "OK" }}
<tr class="body">
{{ else }}
<tr class="body" style="border: solid 2px red;">
{{ end }}
<td class="cell">{{ $md.MetricDescriptor.Name }}</td>
<td class="cell">{{ $md.MetricDescriptor.Type }}</td>
<td class="cell">{{ $md.Status }}</td>
</tr>
{{ end }}
</tbody>
</table>
</div>
</div>
</div>
</body>
</html>