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

Commit e8bcc34

Browse files
Add time series to summary (#54)
1 parent db0a0ed commit e8bcc34

File tree

5 files changed

+125
-29
lines changed

5 files changed

+125
-29
lines changed

cmd/mock_server.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ var (
4848
type summaryTable struct {
4949
Spans []*cloudtrace.Span
5050
MetricDescriptors []*validation.DescriptorStatus
51+
TimeSeries []*validation.TimeSeriesStatus
5152
}
5253

5354
func main() {
@@ -87,7 +88,8 @@ func startStandaloneServer() {
8788
<-sig
8889
grpcServer.GracefulStop()
8990
if *summary {
90-
summaryTable := createSummaryTable(mockTraceServer.SpansSummary(), mockMetricServer.MetricDescriptorSummary())
91+
summaryTable := createSummaryTable(mockTraceServer.SpansSummary(),
92+
mockMetricServer.MetricDescriptorSummary(), mockMetricServer.TimeSeriesSummary())
9193
writeSummaryPage(summaryTable)
9294
}
9395
finish <- true
@@ -99,10 +101,12 @@ func startStandaloneServer() {
99101
<-finish
100102
}
101103

102-
func createSummaryTable(spans []*cloudtrace.Span, descriptors []*validation.DescriptorStatus) summaryTable {
104+
func createSummaryTable(spans []*cloudtrace.Span, descriptors []*validation.DescriptorStatus,
105+
timeSeries []*validation.TimeSeriesStatus) summaryTable {
103106
return summaryTable{
104107
Spans: spans,
105108
MetricDescriptors: descriptors,
109+
TimeSeries: timeSeries,
106110
}
107111
}
108112

internal/validation/mock_metric_validation.go

Lines changed: 51 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,21 @@ type PreviousPoint struct {
7070
Time time.Time
7171
}
7272

73+
// TimeSeriesStruct wraps a TimeSeries with the status of its creation.
74+
// Used in the TimeSeries summary table.
75+
type TimeSeriesStatus struct {
76+
TimeSeries *monitoring.TimeSeries
77+
Status string
78+
}
79+
80+
// TimeSeriesData is a wrapper struct for all the data that the server
81+
// keeps with respect to time series.
82+
type TimeSeriesData struct {
83+
UploadedPoints map[string]*PreviousPoint
84+
TimeSeriesSummary []*TimeSeriesStatus
85+
TimeSeriesLock sync.Mutex
86+
}
87+
7388
// ValidateRequiredFields verifies that the given request contains the required fields.
7489
func ValidateRequiredFields(req interface{}) error {
7590
reqReflect := reflect.ValueOf(req)
@@ -261,45 +276,71 @@ func ValidateRateLimit(timeSeries []*monitoring.TimeSeries, uploadedPoints map[s
261276
}
262277

263278
// ValidateCreateTimeSeries checks that the given TimeSeries conform to the API requirements.
264-
func ValidateCreateTimeSeries(timeSeries []*monitoring.TimeSeries, descriptors map[string]*metric.MetricDescriptor,
265-
uploadedPoints map[string]*PreviousPoint) error {
279+
func ValidateCreateTimeSeries(timeSeries []*monitoring.TimeSeries, timeSeriesData *TimeSeriesData, descriptors map[string]*metric.MetricDescriptor) error {
266280
if len(timeSeries) > maxTimeSeriesPerRequest {
267281
return statusTooManyTimeSeries
268282
}
269283

284+
var overallErr error
270285
for _, ts := range timeSeries {
286+
var currentErr error
287+
271288
// Check that required fields for time series are present.
272289
if ts.Metric == nil || len(ts.Points) != 1 || ts.Resource == nil {
273-
return statusInvalidTimeSeries
290+
addTimeSeriesToSummary(&timeSeriesData.TimeSeriesSummary, ts, statusInvalidTimeSeries.Error())
291+
currentErr = statusInvalidTimeSeries
274292
}
275293

276294
// Check that the metric labels follow the constraints.
277295
for k, v := range ts.Metric.Labels {
278296
if len(k) > maxTimeSeriesLabelKeyBytes {
279-
return statusInvalidTimeSeriesLabelKey
297+
addTimeSeriesToSummary(&timeSeriesData.TimeSeriesSummary, ts, statusInvalidTimeSeriesLabelKey.Error())
298+
currentErr = statusInvalidTimeSeriesLabelKey
280299
}
281300

282301
if len(v) > maxTimeSeriesLabelValueBytes {
283-
return statusInvalidTimeSeriesLabelValue
302+
addTimeSeriesToSummary(&timeSeriesData.TimeSeriesSummary, ts, statusInvalidTimeSeriesLabelValue.Error())
303+
currentErr = statusInvalidTimeSeriesLabelValue
284304
}
285305
}
286306

287307
if err := validateMetricKind(ts, descriptors); err != nil {
288-
return err
308+
addTimeSeriesToSummary(&timeSeriesData.TimeSeriesSummary, ts, err.Error())
309+
currentErr = err
289310
}
290311

291-
if err := validateValueType(ts.ValueType, ts.Points[0]); err != nil {
292-
return err
312+
if len(ts.Points) == 1 {
313+
if err := validateValueType(ts.ValueType, ts.Points[0]); err != nil {
314+
addTimeSeriesToSummary(&timeSeriesData.TimeSeriesSummary, ts, err.Error())
315+
currentErr = err
316+
}
317+
318+
if err := validatePoint(ts, timeSeriesData.UploadedPoints); err != nil {
319+
addTimeSeriesToSummary(&timeSeriesData.TimeSeriesSummary, ts, err.Error())
320+
currentErr = err
321+
}
293322
}
294323

295-
if err := validatePoint(ts, uploadedPoints); err != nil {
296-
return err
324+
if currentErr == nil {
325+
addTimeSeriesToSummary(&timeSeriesData.TimeSeriesSummary, ts, "OK")
326+
} else {
327+
overallErr = currentErr
297328
}
298329
}
299330

331+
if overallErr != nil {
332+
return overallErr
333+
}
300334
return nil
301335
}
302336

337+
func addTimeSeriesToSummary(summary *[]*TimeSeriesStatus, ts *monitoring.TimeSeries, err string) {
338+
*summary = append(*summary, &TimeSeriesStatus{
339+
TimeSeries: ts,
340+
Status: err,
341+
})
342+
}
343+
303344
// validateMetricKind check that if metric_kind is present,
304345
// it is the same as the metricKind of the associated metric.
305346
func validateMetricKind(timeSeries *monitoring.TimeSeries, descriptors map[string]*metric.MetricDescriptor) error {

server/metric/mock_metric.go

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515
package metric
1616

1717
import (
18-
"sync"
19-
2018
"github.com/golang/protobuf/ptypes/empty"
2119
"github.com/googleinterns/cloud-operations-api-mock/internal/validation"
2220
"golang.org/x/net/context"
@@ -32,8 +30,7 @@ import (
3230
type MockMetricServer struct {
3331
monitoring.UnimplementedMetricServiceServer
3432
metricDescriptorData *validation.MetricDescriptorData
35-
uploadedPoints map[string]*validation.PreviousPoint
36-
uploadedPointsLock sync.Mutex
33+
timeSeriesData *validation.TimeSeriesData
3734
}
3835

3936
// NewMockMetricServer creates a new MockMetricServer and returns a pointer to it.
@@ -43,9 +40,12 @@ func NewMockMetricServer() *MockMetricServer {
4340
UploadedMetricDescriptors: uploadedMetricDescriptors,
4441
}
4542
uploadedPoints := make(map[string]*validation.PreviousPoint)
43+
timeSeriesData := &validation.TimeSeriesData{
44+
UploadedPoints: uploadedPoints,
45+
}
4646
return &MockMetricServer{
4747
metricDescriptorData: metricDescriptorData,
48-
uploadedPoints: uploadedPoints,
48+
timeSeriesData: timeSeriesData,
4949
}
5050
}
5151

@@ -152,24 +152,21 @@ func (s *MockMetricServer) ListMetricDescriptors(ctx context.Context, req *monit
152152
// If it already exists, an error is returned.
153153
func (s *MockMetricServer) CreateTimeSeries(ctx context.Context, req *monitoring.CreateTimeSeriesRequest,
154154
) (*empty.Empty, error) {
155-
s.uploadedPointsLock.Lock()
156-
if err := validation.ValidateRateLimit(req.TimeSeries, s.uploadedPoints); err != nil {
157-
s.uploadedPointsLock.Unlock()
155+
s.timeSeriesData.TimeSeriesLock.Lock()
156+
defer s.timeSeriesData.TimeSeriesLock.Unlock()
157+
if err := validation.ValidateRateLimit(req.TimeSeries, s.timeSeriesData.UploadedPoints); err != nil {
158158
return nil, err
159159
}
160-
s.uploadedPointsLock.Unlock()
161160
if err := validation.ValidateRequiredFields(req); err != nil {
162161
return nil, err
163162
}
164163
if err := validation.ValidateProjectName(req.Name); err != nil {
165164
return nil, err
166165
}
167-
if err := validation.ValidateCreateTimeSeries(req.TimeSeries, s.metricDescriptorData.UploadedMetricDescriptors, s.uploadedPoints); err != nil {
166+
if err := validation.ValidateCreateTimeSeries(req.TimeSeries, s.timeSeriesData, s.metricDescriptorData.UploadedMetricDescriptors); err != nil {
168167
return nil, err
169168
}
170-
s.uploadedPointsLock.Lock()
171-
defer s.uploadedPointsLock.Unlock()
172-
validation.AddPoint(req.TimeSeries, s.uploadedPoints)
169+
validation.AddPoint(req.TimeSeries, s.timeSeriesData.UploadedPoints)
173170
return &empty.Empty{}, nil
174171
}
175172

@@ -199,3 +196,8 @@ func addMetricDescriptorToSummary(summary *[]*validation.DescriptorStatus, metri
199196
func (s *MockMetricServer) MetricDescriptorSummary() []*validation.DescriptorStatus {
200197
return s.metricDescriptorData.MetricDescriptorSummary
201198
}
199+
200+
// TimeSeriesSummary returns the time series data to display in the summary page.
201+
func (s *MockMetricServer) TimeSeriesSummary() []*validation.TimeSeriesStatus {
202+
return s.timeSeriesData.TimeSeriesSummary
203+
}

static/css/main.css

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ body, html {
2222
align-items: center;
2323
justify-content: center;
2424
flex-wrap: wrap;
25-
padding: 33px 30px;
25+
padding: 0 60px 60px;
2626
}
2727

2828
.summary {
@@ -92,3 +92,10 @@ th, td {
9292
color: #808080;
9393
line-height: 1.4;
9494
}
95+
96+
.title {
97+
color: #6c7ae0;
98+
text-decoration: underline;
99+
padding-top: 50px;
100+
padding-bottom: 50px;
101+
}

static/summary_template.html

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
<div class="container-summary">
1111

1212
<!-- Trace table -->
13-
<h1 style="color: #6c7ae0; text-decoration: underline;">Trace Summary</h1>
13+
<h1 class="title">Trace</h1>
1414
<div class="summary">
1515
<div class="summary-head">
1616
<table>
@@ -43,7 +43,7 @@ <h1 style="color: #6c7ae0; text-decoration: underline;">Trace Summary</h1>
4343
</div>
4444

4545
<!-- Metric Descriptor table -->
46-
<h1 style="color: #6c7ae0; text-decoration: underline;">Metric Descriptors Summary</h1>
46+
<h1 class="title">Metric Descriptors</h1>
4747
<div class="summary">
4848
<div class="summary-head">
4949
<table>
@@ -56,7 +56,6 @@ <h1 style="color: #6c7ae0; text-decoration: underline;">Metric Descriptors Summa
5656
</thead>
5757
</table>
5858
</div>
59-
6059
<div class="summary-body">
6160
<table>
6261
<tbody>
@@ -75,6 +74,49 @@ <h1 style="color: #6c7ae0; text-decoration: underline;">Metric Descriptors Summa
7574
</table>
7675
</div>
7776
</div>
77+
78+
<!-- Time Series table -->
79+
<h1 class="title">Time Series</h1>
80+
<div class="summary">
81+
<div class="summary-head">
82+
<table>
83+
<thead>
84+
<tr class="head">
85+
<th class="cell">Metric Type</th>
86+
<th class="cell">Metric Labels</th>
87+
<th class="cell">Monitored Resource Type</th>
88+
<th class="cell">Monitored Resource Labels</th>
89+
<th class="cell">Point Interval</th>
90+
<th class="cell">Status</th>
91+
</tr>
92+
</thead>
93+
</table>
94+
</div>
95+
<div class="summary-body">
96+
<table>
97+
<tbody>
98+
{{ range $index, $ts := .TimeSeries }}
99+
{{ if eq $ts.Status "OK" }}
100+
<tr class="body">
101+
{{ else }}
102+
<tr class="body" style="border: solid 2px red;">
103+
{{ end }}
104+
<td class="cell">{{ $ts.TimeSeries.Metric.Type }}</td>
105+
<td class="cell">{{ $ts.TimeSeries.Metric.Labels }}</td>
106+
<td class="cell">{{ $ts.TimeSeries.Resource.Type }}</td>
107+
<td class="cell">{{ $ts.TimeSeries.Resource.Labels }}</td>
108+
{{ if $ts.TimeSeries.Points }}
109+
<td class="cell">{{ (index $ts.TimeSeries.Points 0).Interval }}</td>
110+
{{ else }}
111+
<td class="cell">Missing Point</td>
112+
{{ end }}
113+
<td class="cell">{{ $ts.Status }}</td>
114+
</tr>
115+
{{ end }}
116+
</tbody>
117+
</table>
118+
</div>
119+
</div>
78120
</div>
79121
</body>
80122
</html>

0 commit comments

Comments
 (0)