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

Commit

Permalink
Add summary object for metric descriptors (#52)
Browse files Browse the repository at this point in the history
Add metric descriptor to HTML
  • Loading branch information
the-ericwang35 authored Aug 7, 2020
1 parent 649245c commit db0a0ed
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 27 deletions.
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>

0 comments on commit db0a0ed

Please sign in to comment.