blob: ee027255711670c1b79f5a9fb47d04c5bca6cabf [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This file implements outputLanguage for JSON.
package source_generator
import (
"config"
"encoding/json"
)
type jsonOutputter struct{}
// JSON export structure
// go tags set the field name when exported to JSON data.
type jsonRegistry struct {
Customers []jsonCustomer `json:"customers"`
}
type jsonCustomer struct {
Name string `json:"name"`
Id uint32 `json:"id"`
Projects []jsonProject `json:"projects"`
}
type jsonProject struct {
Name string `json:"name"`
Id uint32 `json:"id"`
Contact string `json:"project_contact"`
Metrics []jsonMetric `json:"metrics"`
}
type jsonMetric struct {
Name string `json:"name"`
Id uint32 `json:"id"`
MetricType string `json:"metric_type"`
ExpirationDate string `json:"expiration_date"`
Dimensions []string `json:"dimensions"`
MaxEventCode []uint32 `json:"max_event_code"`
Semantics []string `json:"metric_semantics"`
Units string `json:"metric_units"`
UnitsOther string `json:"metric_units_other"`
StringCandidateFile string `json:"string_candidate_file"`
Reports []jsonReport `json:"reports"`
}
type jsonReport struct {
Name string `json:"name"`
Id uint32 `json:"id"`
ReportType string `json:"report_type"`
ReportTypeId int32 `json:"report_type_id"`
PrivacyLevel string `json:"privacy_level"`
EventVectorBufferMax uint64 `json:"event_vector_buffer_max"`
StringBufferMax uint32 `json:"string_buffer_max"`
SystemProfileField []string `json:"system_profile_field"`
LocalAggregationPeriod int32 `json:"local_aggregation_period"`
LocalAggregationProcedure string `json:"local_aggregation_procedure"`
LocalAggregationProcedurePercentileN uint32 `json:"local_aggregation_procedure_percentile_n"`
ExperimentId []int64 `json:"experiment_id"`
}
// Generates a list of evenly distributed integer values
// between |start| and |stop| of length |num|.
func linspace(start, stop, num uint64) []uint64 {
step := float64(stop-start) / float64(num-1)
elements := make([]uint64, num)
for x := range elements {
elements[x] = uint64(float64(start) + step*float64(x))
}
return elements
}
// JSON struct constructors
func (jo *jsonOutputter) makeJSONReport(report *config.ReportDefinition, metric *config.MetricDefinition) jsonReport {
if report == nil {
return jsonReport{}
}
var systemProfileField []string
for _, f := range report.GetSystemProfileField() {
systemProfileField = append(systemProfileField, f.String())
}
return jsonReport{
Name: report.GetReportName(),
Id: report.GetId(),
ReportType: report.GetReportType().String(),
ReportTypeId: int32(report.GetReportType()),
PrivacyLevel: report.GetPrivacyLevel().String(),
EventVectorBufferMax: report.GetEventVectorBufferMax(),
StringBufferMax: report.GetStringBufferMax(),
SystemProfileField: systemProfileField,
LocalAggregationPeriod: int32(report.GetLocalAggregationPeriod()),
LocalAggregationProcedure: report.GetLocalAggregationProcedure().String(),
LocalAggregationProcedurePercentileN: report.GetLocalAggregationProcedurePercentileN(),
ExperimentId: report.GetExperimentId(),
}
}
func (jo *jsonOutputter) makeJSONMetric(metric *config.MetricDefinition) jsonMetric {
if metric == nil {
return jsonMetric{}
}
var expirationDate string
if metric.GetMetaData() != nil {
expirationDate = metric.GetMetaData().GetExpirationDate()
}
var reports []jsonReport
for _, r := range metric.GetReports() {
reports = append(reports, jo.makeJSONReport(r, metric))
}
var dimensions []string
var maxEventCodes []uint32
for _, d := range metric.GetMetricDimensions() {
dimensions = append(dimensions, d.GetDimension())
maxEventCodes = append(maxEventCodes, d.GetMaxEventCode())
}
var semantics []string
for _, s := range metric.GetMetricSemantics() {
semantics = append(semantics, s.String())
}
return jsonMetric{
Name: metric.GetMetricName(),
Id: metric.GetId(),
MetricType: metric.GetMetricType().String(),
ExpirationDate: expirationDate,
Dimensions: dimensions,
MaxEventCode: maxEventCodes,
Semantics: semantics,
Units: metric.GetMetricUnits().String(),
UnitsOther: metric.GetMetricUnitsOther(),
StringCandidateFile: metric.GetStringCandidateFile(),
Reports: reports,
}
}
func (jo *jsonOutputter) makeJSONProject(project *config.ProjectConfig) jsonProject {
if project == nil {
return jsonProject{}
}
var metrics []jsonMetric
for _, m := range project.GetMetrics() {
metrics = append(metrics, jo.makeJSONMetric(m))
}
return jsonProject{
Name: project.GetProjectName(),
Id: project.GetProjectId(),
Contact: project.GetProjectContact(),
Metrics: metrics,
}
}
func (jo *jsonOutputter) makeJSONCustomer(customer *config.CustomerConfig) jsonCustomer {
if customer == nil {
return jsonCustomer{}
}
var projects []jsonProject
for _, p := range customer.GetProjects() {
projects = append(projects, jo.makeJSONProject(p))
}
return jsonCustomer{
Name: customer.GetCustomerName(),
Id: customer.GetCustomerId(),
Projects: projects,
}
}
func (jo *jsonOutputter) makeJSONRegistry(registry *config.CobaltRegistry) jsonRegistry {
if registry == nil {
return jsonRegistry{}
}
var customers []jsonCustomer
for _, c := range registry.GetCustomers() {
customers = append(customers, jo.makeJSONCustomer(c))
}
return jsonRegistry{
Customers: customers,
}
}
// Outputs the registry contents in JSON
func (jo *jsonOutputter) JSONOutput(_, filtered *config.CobaltRegistry) (outputBytes []byte, err error) {
jsonRegistry := jo.makeJSONRegistry(filtered)
prefix := ""
indent := " "
jsonBytes, err := json.MarshalIndent(jsonRegistry, prefix, indent)
if err != nil {
return nil, err
}
return jsonBytes, nil
}
// Returns an output formatter for JSON
func JSONOutputFactory() OutputFormatter {
jo := jsonOutputter{}
return jo.JSONOutput
}