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

Commit db0a0ed

Browse files
Add summary object for metric descriptors (#52)
Add metric descriptor to HTML
1 parent 649245c commit db0a0ed

File tree

5 files changed

+118
-27
lines changed

5 files changed

+118
-27
lines changed

cmd/mock_server.go

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import (
2424
"syscall"
2525

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

46+
// summaryTable wraps the summaries for both trace and metrics,
47+
// and is used to pass data to the HTML template.
48+
type summaryTable struct {
49+
Spans []*cloudtrace.Span
50+
MetricDescriptors []*validation.DescriptorStatus
51+
}
52+
4653
func main() {
4754
flag.Parse()
4855
startStandaloneServer()
@@ -60,10 +67,13 @@ func startStandaloneServer() {
6067
}
6168

6269
grpcServer := grpc.NewServer()
70+
6371
mockTraceServer := trace.NewMockTraceServer()
6472
cloudtrace.RegisterTraceServiceServer(grpcServer, mockTraceServer)
6573
mocktrace.RegisterMockTraceServiceServer(grpcServer, mockTraceServer)
66-
monitoring.RegisterMetricServiceServer(grpcServer, metric.NewMockMetricServer())
74+
75+
mockMetricServer := metric.NewMockMetricServer()
76+
monitoring.RegisterMetricServiceServer(grpcServer, mockMetricServer)
6777

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

@@ -77,7 +87,8 @@ func startStandaloneServer() {
7787
<-sig
7888
grpcServer.GracefulStop()
7989
if *summary {
80-
writeSummaryPage(mockTraceServer.ResultTable())
90+
summaryTable := createSummaryTable(mockTraceServer.SpansSummary(), mockMetricServer.MetricDescriptorSummary())
91+
writeSummaryPage(summaryTable)
8192
}
8293
finish <- true
8394
}()
@@ -88,14 +99,21 @@ func startStandaloneServer() {
8899
<-finish
89100
}
90101

102+
func createSummaryTable(spans []*cloudtrace.Span, descriptors []*validation.DescriptorStatus) summaryTable {
103+
return summaryTable{
104+
Spans: spans,
105+
MetricDescriptors: descriptors,
106+
}
107+
}
108+
91109
// writeSummaryPage creates summary.html from the results and the template HTML.
92-
func writeSummaryPage(results []*cloudtrace.Span) {
110+
func writeSummaryPage(table summaryTable) {
93111
outputFile, err := os.Create("../static/summary.html")
94112
if err != nil {
95113
panic(err)
96114
}
97115
t := template.Must(template.ParseFiles("../static/summary_template.html"))
98-
err = t.Execute(outputFile, results)
116+
err = t.Execute(outputFile, table)
99117
if err != nil {
100118
panic(err)
101119
}

internal/validation/mock_metric_validation.go

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"reflect"
2020
"regexp"
2121
"strings"
22+
"sync"
2223
"time"
2324

2425
"github.com/golang/protobuf/ptypes"
@@ -42,11 +43,26 @@ const (
4243
// Service name regex sourced from https://github.com/asaskevich/govalidator/blob/master/patterns.go#L33
4344
var (
4445
labelKeyRegex = regexp.MustCompile("[a-z][a-zA0-9_-]*")
45-
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})*[\._]?$`)
46+
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})*[._]?$`)
4647
relativeMetricNameRegex = regexp.MustCompile("[A-Za-z0-9_/]{1,100}")
47-
diplayNameRegex = regexp.MustCompile(`opentelemetry\/.*`)
48+
displayNameRegex = regexp.MustCompile(`opentelemetry/.*`)
4849
)
4950

51+
// MetricDescriptorStatus wraps a MetricDescriptor with the status of its creation.
52+
// Used in the MetricDescriptor summary table.
53+
type DescriptorStatus struct {
54+
MetricDescriptor *metric.MetricDescriptor
55+
Status string
56+
}
57+
58+
// MetricDescriptorData is a wrapper struct for all the data that the server
59+
// keeps with respect to metric descriptors.
60+
type MetricDescriptorData struct {
61+
UploadedMetricDescriptors map[string]*metric.MetricDescriptor
62+
MetricDescriptorSummary []*DescriptorStatus
63+
MetricDescriptorsLock sync.Mutex
64+
}
65+
5066
// PreviousPoint contains information about the most recently uploaded
5167
// point for a time series.
5268
type PreviousPoint struct {
@@ -142,7 +158,7 @@ func validateLabels(labels []*lbl.LabelDescriptor) error {
142158
}
143159

144160
func validateMetricDisplayName(displayName string) error {
145-
if !diplayNameRegex.MatchString(displayName) {
161+
if !displayNameRegex.MatchString(displayName) {
146162
return statusInvalidDisplayName
147163
}
148164

server/metric/mock_metric.go

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -31,19 +31,21 @@ import (
3131
// uploaded data.
3232
type MockMetricServer struct {
3333
monitoring.UnimplementedMetricServiceServer
34-
uploadedMetricDescriptors map[string]*metric.MetricDescriptor
35-
uploadedMetricDescriptorsLock sync.Mutex
36-
uploadedPoints map[string]*validation.PreviousPoint
37-
uploadedPointsLock sync.Mutex
34+
metricDescriptorData *validation.MetricDescriptorData
35+
uploadedPoints map[string]*validation.PreviousPoint
36+
uploadedPointsLock sync.Mutex
3837
}
3938

4039
// NewMockMetricServer creates a new MockMetricServer and returns a pointer to it.
4140
func NewMockMetricServer() *MockMetricServer {
4241
uploadedMetricDescriptors := make(map[string]*metric.MetricDescriptor)
42+
metricDescriptorData := &validation.MetricDescriptorData{
43+
UploadedMetricDescriptors: uploadedMetricDescriptors,
44+
}
4345
uploadedPoints := make(map[string]*validation.PreviousPoint)
4446
return &MockMetricServer{
45-
uploadedMetricDescriptors: uploadedMetricDescriptors,
46-
uploadedPoints: uploadedPoints,
47+
metricDescriptorData: metricDescriptorData,
48+
uploadedPoints: uploadedPoints,
4749
}
4850
}
4951

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

80-
s.uploadedMetricDescriptorsLock.Lock()
81-
defer s.uploadedMetricDescriptorsLock.Unlock()
82-
metricDescriptor, err := validation.AccessMetricDescriptor(s.uploadedMetricDescriptors, req.Name)
82+
s.metricDescriptorData.MetricDescriptorsLock.Lock()
83+
defer s.metricDescriptorData.MetricDescriptorsLock.Unlock()
84+
metricDescriptor, err := validation.AccessMetricDescriptor(s.metricDescriptorData.UploadedMetricDescriptors, req.Name)
8385
if err != nil {
8486
return nil, err
8587
}
@@ -92,23 +94,28 @@ func (s *MockMetricServer) GetMetricDescriptor(ctx context.Context, req *monitor
9294
func (s *MockMetricServer) CreateMetricDescriptor(ctx context.Context, req *monitoring.CreateMetricDescriptorRequest,
9395
) (*metric.MetricDescriptor, error) {
9496
if err := validation.ValidateRequiredFields(req); err != nil {
97+
addMetricDescriptorToSummary(&s.metricDescriptorData.MetricDescriptorSummary, req.MetricDescriptor, err.Error())
9598
return nil, err
9699
}
97100

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

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

106-
s.uploadedMetricDescriptorsLock.Lock()
107-
defer s.uploadedMetricDescriptorsLock.Unlock()
108-
if err := validation.AddMetricDescriptor(s.uploadedMetricDescriptors, req.MetricDescriptor.Type, req.MetricDescriptor); err != nil {
111+
s.metricDescriptorData.MetricDescriptorsLock.Lock()
112+
defer s.metricDescriptorData.MetricDescriptorsLock.Unlock()
113+
if err := validation.AddMetricDescriptor(s.metricDescriptorData.UploadedMetricDescriptors, req.MetricDescriptor.Type, req.MetricDescriptor); err != nil {
114+
addMetricDescriptorToSummary(&s.metricDescriptorData.MetricDescriptorSummary, req.MetricDescriptor, err.Error())
109115
return nil, err
110116
}
111117

118+
addMetricDescriptorToSummary(&s.metricDescriptorData.MetricDescriptorSummary, req.MetricDescriptor, "OK")
112119
return req.MetricDescriptor, nil
113120
}
114121

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

123-
s.uploadedMetricDescriptorsLock.Lock()
124-
defer s.uploadedMetricDescriptorsLock.Unlock()
125-
if err := validation.RemoveMetricDescriptor(s.uploadedMetricDescriptors, req.Name); err != nil {
130+
s.metricDescriptorData.MetricDescriptorsLock.Lock()
131+
defer s.metricDescriptorData.MetricDescriptorsLock.Unlock()
132+
if err := validation.RemoveMetricDescriptor(s.metricDescriptorData.UploadedMetricDescriptors, req.Name); err != nil {
126133
return nil, err
127134
}
128135

@@ -157,7 +164,7 @@ func (s *MockMetricServer) CreateTimeSeries(ctx context.Context, req *monitoring
157164
if err := validation.ValidateProjectName(req.Name); err != nil {
158165
return nil, err
159166
}
160-
if err := validation.ValidateCreateTimeSeries(req.TimeSeries, s.uploadedMetricDescriptors, s.uploadedPoints); err != nil {
167+
if err := validation.ValidateCreateTimeSeries(req.TimeSeries, s.metricDescriptorData.UploadedMetricDescriptors, s.uploadedPoints); err != nil {
161168
return nil, err
162169
}
163170
s.uploadedPointsLock.Lock()
@@ -178,3 +185,17 @@ func (s *MockMetricServer) ListTimeSeries(ctx context.Context, req *monitoring.L
178185
ExecutionErrors: []*status.Status{},
179186
}, nil
180187
}
188+
189+
// addMetricDescriptorToSummary adds the given metric descriptor and status to the summary.
190+
func addMetricDescriptorToSummary(summary *[]*validation.DescriptorStatus, metricDescriptor *metric.MetricDescriptor, err string) {
191+
metricDescriptorStatus := &validation.DescriptorStatus{
192+
MetricDescriptor: metricDescriptor,
193+
Status: err,
194+
}
195+
*summary = append(*summary, metricDescriptorStatus)
196+
}
197+
198+
// MetricDescriptorSummary returns the metric descriptor data to display in the summary page.
199+
func (s *MockMetricServer) MetricDescriptorSummary() []*validation.DescriptorStatus {
200+
return s.metricDescriptorData.MetricDescriptorSummary
201+
}

server/trace/mock_trace.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,6 @@ func (s *MockTraceServer) SetOnUpload(onUpload func(ctx context.Context, spans [
123123
s.onUpload = onUpload
124124
}
125125

126-
func (s *MockTraceServer) ResultTable() []*cloudtrace.Span {
126+
func (s *MockTraceServer) SpansSummary() []*cloudtrace.Span {
127127
return s.spanData.SpansSummary
128128
}

static/summary_template.html

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
</head>
99
<body>
1010
<div class="container-summary">
11+
12+
<!-- Trace table -->
13+
<h1 style="color: #6c7ae0; text-decoration: underline;">Trace Summary</h1>
1114
<div class="summary">
1215
<div class="summary-head">
1316
<table>
@@ -20,11 +23,10 @@
2023
</thead>
2124
</table>
2225
</div>
23-
2426
<div class="summary-body">
2527
<table>
2628
<tbody>
27-
{{ range $index, $span := . }}
29+
{{ range $index, $span := .Spans }}
2830
{{ if eq $span.Status.Message "OK" }}
2931
<tr class="body">
3032
{{ else }}
@@ -39,6 +41,40 @@
3941
</table>
4042
</div>
4143
</div>
44+
45+
<!-- Metric Descriptor table -->
46+
<h1 style="color: #6c7ae0; text-decoration: underline;">Metric Descriptors Summary</h1>
47+
<div class="summary">
48+
<div class="summary-head">
49+
<table>
50+
<thead>
51+
<tr class="head">
52+
<th class="cell">Metric Descriptor Name</th>
53+
<th class="cell">Metric Descriptor Type</th>
54+
<th class="cell">Status</th>
55+
</tr>
56+
</thead>
57+
</table>
58+
</div>
59+
60+
<div class="summary-body">
61+
<table>
62+
<tbody>
63+
{{ range $index, $md := .MetricDescriptors }}
64+
{{ if eq $md.Status "OK" }}
65+
<tr class="body">
66+
{{ else }}
67+
<tr class="body" style="border: solid 2px red;">
68+
{{ end }}
69+
<td class="cell">{{ $md.MetricDescriptor.Name }}</td>
70+
<td class="cell">{{ $md.MetricDescriptor.Type }}</td>
71+
<td class="cell">{{ $md.Status }}</td>
72+
</tr>
73+
{{ end }}
74+
</tbody>
75+
</table>
76+
</div>
77+
</div>
4278
</div>
4379
</body>
4480
</html>

0 commit comments

Comments
 (0)