[config_parser] Support filtering fields on client
The support for reading field descriptors in golang's protobuf library
requires reflection and the 'descriptor' library. It's gross, but
AFACT it's the *correct* way of doing things.
See: https://github.com/golang/protobuf/issues/358
CB-199 #comment
Fields can now easily be filtered by adding the annotation:
[(cobalt_options).hide_on_client = true]
Change-Id: Ie96f445fe9a1a26760d171e9b7c2a76b72111422
diff --git a/config/BUILD.gn b/config/BUILD.gn
index 3b8d9b6..e0fe1e0 100644
--- a/config/BUILD.gn
+++ b/config/BUILD.gn
@@ -12,6 +12,7 @@
proto_in_dir = "//third_party/cobalt"
sources = [
"cobalt_config.proto",
+ "annotations.proto",
"encodings.proto",
"metric_definition.proto",
"metrics.proto",
diff --git a/config/CMakeLists.txt b/config/CMakeLists.txt
index d83736c..a4fe73b 100644
--- a/config/CMakeLists.txt
+++ b/config/CMakeLists.txt
@@ -25,14 +25,15 @@
false
encodings metrics metric_definition
report_configs report_definition
- cobalt_config window_size project)
+ cobalt_config window_size annotations project)
# Generate Go bindings for the config .proto files.
cobalt_protobuf_generate_go(generate_config_pb_go_files
CONFIG_PB_GO_FILES
false
cobalt_config encodings metrics metric_definition
- report_configs report_definition window_size)
+ report_configs report_definition window_size
+ annotations project)
add_library(buckets_config
buckets_config.cc
diff --git a/config/annotations.proto b/config/annotations.proto
new file mode 100644
index 0000000..132f23e
--- /dev/null
+++ b/config/annotations.proto
@@ -0,0 +1,18 @@
+// Copyright 2018 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.
+syntax = "proto3";
+
+package cobalt;
+
+import "google/protobuf/descriptor.proto";
+
+option go_package = "config";
+
+message CobaltOptions {
+ bool hide_on_client = 1;
+}
+
+extend google.protobuf.FieldOptions {
+ CobaltOptions cobalt_options = 50000;
+}
diff --git a/config/config_parser/CMakeLists.txt b/config/config_parser/CMakeLists.txt
index 3373513..f339c86 100644
--- a/config/config_parser/CMakeLists.txt
+++ b/config/config_parser/CMakeLists.txt
@@ -32,7 +32,8 @@
${CMAKE_CURRENT_SOURCE_DIR}/src/config_parser/project_config.go
${CMAKE_CURRENT_SOURCE_DIR}/src/config_parser/git.go
${CMAKE_CURRENT_SOURCE_DIR}/src/config_parser/config_reader.go
- ${CMAKE_CURRENT_SOURCE_DIR}/src/config_parser/id.go)
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/config_parser/id.go
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/config_parser/filter.go)
set(CONFIG_VALIDATOR_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/config_validator/validator.go
${CMAKE_CURRENT_SOURCE_DIR}/src/config_validator/system_profile_field.go
@@ -69,7 +70,8 @@
set(CONFIG_PARSER_TEST_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/config_parser/project_list_test.go
${CMAKE_CURRENT_SOURCE_DIR}/src/config_parser/config_reader_test.go
${CMAKE_CURRENT_SOURCE_DIR}/src/config_parser/id_test.go
- ${CMAKE_CURRENT_SOURCE_DIR}/src/config_parser/project_config_test.go)
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/config_parser/project_config_test.go
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/config_parser/filter_test.go)
add_custom_command(OUTPUT ${CONFIG_PARSER_TEST_BIN}
COMMAND ${GO_BIN} test -c -o ${CONFIG_PARSER_TEST_BIN} ${CONFIG_PARSER_TEST_SRC} ${CONFIG_PARSER_SRC}
diff --git a/config/config_parser/src/config_parser/filter.go b/config/config_parser/src/config_parser/filter.go
new file mode 100644
index 0000000..5900e61
--- /dev/null
+++ b/config/config_parser/src/config_parser/filter.go
@@ -0,0 +1,136 @@
+package config_parser
+
+import (
+ "config"
+ "reflect"
+ "strings"
+
+ "github.com/golang/glog"
+ "github.com/golang/protobuf/descriptor"
+ "github.com/golang/protobuf/proto"
+ descriptor_pb "github.com/golang/protobuf/protoc-gen-go/descriptor"
+)
+
+func FilterHideOnClient(c *config.CobaltConfig) {
+ filterReflectedValue(reflect.ValueOf(c))
+}
+
+func filterWithCobaltOptions(options *config.CobaltOptions, field reflect.Value) {
+ if options.HideOnClient {
+ // Set the field to its zero value (in proto-land this is the same as
+ // unsetting the value).
+ field.Set(reflect.Zero(field.Type()))
+ }
+}
+
+func filterPointer(rc reflect.Value) {
+ if rc.IsNil() {
+ return
+ }
+
+ // get the value of the pointer.
+ msgValue := rc.Elem()
+
+ // Check if we can treat rc as a descriptor.Message
+ msgInterface, ok := rc.Interface().(descriptor.Message)
+
+ if !ok {
+ // This might be a oneof wrapper struct, so we treat it as a generic
+ // struct and blindly recurse through all fields.
+ filterReflectedValue(msgValue)
+ return
+ }
+
+ // The way that golang handles oneof fields does not map 1:1 onto the logical
+ // protobuf structure. It is implemented as a golang interface for each of the
+ // possible variants. Since we can't easily look up the descriptor information
+ // for individual oneof variants, we ignore them and simply try to filter the
+ // value.
+ for i := 0; i < msgValue.NumField(); i++ {
+ if msgValue.Type().Field(i).Tag.Get("protobuf_oneof") != "" {
+ filterReflectedValue(reflect.ValueOf(msgValue.Field(i).Interface()))
+ }
+ }
+
+ // Get message's proto descriptor information
+ _, msgDescriptor := descriptor.ForMessage(msgInterface)
+ for _, field := range msgDescriptor.GetField() {
+ filterMessageField(field, msgValue)
+ }
+}
+
+func findFieldWithinStruct(name string, rc reflect.Value) (foundField int) {
+ foundField = -1
+
+ nameTag := "name=" + name + ","
+ // Search through the struct for a matching field tag (there's no way to
+ // convert field.GetName() to the generated field name, so we're stuck
+ // with this See: https://github.com/golang/protobuf/issues/457)
+ for i := 0; i < rc.NumField(); i++ {
+ // The go protobuf compiler adds tags to the generated go code. One of those
+ // tags is called 'protobuf' and contains key-value entries, one of which is
+ // the name of the field in the proto file.
+ if strings.Contains(rc.Type().Field(i).Tag.Get("protobuf"), nameTag) {
+ foundField = i
+ break
+ }
+ }
+
+ return foundField
+}
+
+func filterMessageField(field *descriptor_pb.FieldDescriptorProto, msgValue reflect.Value) {
+ foundField := findFieldWithinStruct(field.GetName(), msgValue)
+
+ // Oneof fields are not treated the same as other fields, so there will be
+ // a "field" at this level, that has no corresponding real field in the
+ // struct. This means that we have no straightforward way of filtering
+ // individual oneof variants, or a oneof field as a whole. We can filter
+ // within the sub-messages, but at the level of oneof, our handling is subtly
+ // broken.
+ if foundField < 0 {
+ return
+ }
+
+ // Finally, we can extract the CobaltOptions extension.
+ if options_extension, err := proto.GetExtension(field.GetOptions(), config.E_CobaltOptions); err == nil {
+ filterWithCobaltOptions(options_extension.(*config.CobaltOptions), msgValue.Field(foundField))
+ }
+
+ // Recurse for the sub message.
+ filterReflectedValue(msgValue.Field(foundField))
+}
+
+func filterReflectedValue(rc reflect.Value) {
+ switch rc.Kind() {
+ case reflect.Ptr:
+ filterPointer(rc)
+ case reflect.Struct:
+ for i := 0; i < rc.NumField(); i++ {
+ filterReflectedValue(rc.Field(i))
+ }
+ case reflect.Array, reflect.Slice:
+ for i := 0; i < rc.Len(); i++ {
+ filterReflectedValue(rc.Index(i))
+ }
+ case reflect.Map:
+ for _, k := range rc.MapKeys() {
+ filterReflectedValue(rc.MapIndex(k))
+ }
+ case
+ reflect.Uint, reflect.Int,
+ reflect.Uint8, reflect.Int8,
+ reflect.Uint16, reflect.Int16,
+ reflect.Uint32, reflect.Int32,
+ reflect.Uint64, reflect.Int64,
+ reflect.Float32, reflect.Float64,
+ reflect.String, reflect.Bool:
+ // These are expected base-cases. It may be extended when more field types are
+ // used in the config proto.
+ return
+ case reflect.Invalid:
+ // This is likely generated by filter_test.go.
+ default:
+ glog.Exitf("Unexpected type found in protobuf: %v. If this is expected, add another value to the case in filter.go", rc.Kind())
+ }
+}
diff --git a/config/config_parser/src/config_parser/filter_test.go b/config/config_parser/src/config_parser/filter_test.go
new file mode 100644
index 0000000..1abe3aa
--- /dev/null
+++ b/config/config_parser/src/config_parser/filter_test.go
@@ -0,0 +1,100 @@
+package config_parser
+
+import (
+ "config"
+ "reflect"
+ "testing"
+
+ "github.com/golang/protobuf/proto"
+)
+
+var filterTests = []struct {
+ before proto.Message
+ after proto.Message
+}{
+ {
+ before: &config.MetricDefinition{
+ MetricName: "A Metric!",
+ MetaData: &config.MetricDefinition_Metadata{
+ ExpirationDate: "A DATE!",
+ Owner: []string{"Someone"},
+ },
+ },
+ after: &config.MetricDefinition{
+ MetricName: "A Metric!",
+ MetaData: &config.MetricDefinition_Metadata{},
+ },
+ },
+
+ {
+ before: &config.MetricDefinition{
+ MetricName: "A Metric!",
+ EventCodes: map[uint32]string{
+ 0: "An event code",
+ },
+ },
+ after: &config.MetricDefinition{
+ MetricName: "A Metric!",
+ },
+ },
+
+ {
+ before: &config.ReportDefinition{
+ ReportName: "A Report!",
+ CandidateList: []string{"Candidate1", "Candidate2", "Candidate3"},
+ },
+ after: &config.ReportDefinition{
+ ReportName: "A Report!",
+ },
+ },
+
+ {
+ before: &config.CobaltConfig{
+ Customers: []*config.CustomerConfig{
+ &config.CustomerConfig{
+ Projects: []*config.ProjectConfig{
+ &config.ProjectConfig{
+ Metrics: []*config.MetricDefinition{
+ &config.MetricDefinition{
+ MetricName: "A Metric!",
+ EventCodes: map[uint32]string{
+ 0: "An event code",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ after: &config.CobaltConfig{
+ Customers: []*config.CustomerConfig{
+ &config.CustomerConfig{
+ Projects: []*config.ProjectConfig{
+ &config.ProjectConfig{
+ Metrics: []*config.MetricDefinition{
+ &config.MetricDefinition{
+ MetricName: "A Metric!",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+}
+
+func TestFilter(t *testing.T) {
+ for _, tt := range filterTests {
+ if proto.Equal(tt.before, tt.after) {
+ t.Errorf("%v\n==\n%v", proto.MarshalTextString(tt.before), proto.MarshalTextString(tt.after))
+ }
+
+ filterReflectedValue(reflect.ValueOf(tt.before))
+
+ if !proto.Equal(tt.before, tt.after) {
+ t.Errorf("%v\n!=\n%v", proto.MarshalTextString(tt.before), proto.MarshalTextString(tt.after))
+ }
+ }
+}
diff --git a/config/config_parser/src/config_parser_main.go b/config/config_parser/src/config_parser_main.go
index 5782e9e..fb31574 100644
--- a/config/config_parser/src/config_parser_main.go
+++ b/config/config_parser/src/config_parser_main.go
@@ -8,6 +8,7 @@
package main
import (
+ "config"
"config_parser"
"config_validator"
"flag"
@@ -20,6 +21,7 @@
"time"
"github.com/golang/glog"
+ "github.com/golang/protobuf/proto"
)
var (
@@ -40,6 +42,7 @@
varName = flag.String("var_name", "config", "When using the 'cpp' or 'dart' output format, this will specify the variable name to be used in the output.")
namespace = flag.String("namespace", "", "When using the 'cpp' or 'rust' output format, this will specify the comma-separated namespace within which the config variable must be places.")
depFile = flag.String("dep_file", "", "Generate a depfile (see gn documentation) that lists all the project configuration files. Requires -output_file and -config_dir.")
+ forClient = flag.Bool("for_client", false, "Filters out the hide_on_client tagged fields")
dartOutDir = flag.String("dart_out_dir", "", "The directory to write dart files to (if different from out_dir)")
)
@@ -181,6 +184,11 @@
}
c := config_parser.MergeConfigs(configs)
+ filtered := proto.Clone(&c).(*config.CobaltConfig)
+
+ if *forClient {
+ config_parser.FilterHideOnClient(filtered)
+ }
for _, format := range outFormats {
var outputFormatter source_generator.OutputFormatter
@@ -214,7 +222,7 @@
}
// Then, we serialize the configuration.
- configBytes, err := outputFormatter(&c)
+ configBytes, err := outputFormatter(&c, filtered)
if err != nil {
glog.Exit(err)
}
diff --git a/config/config_parser/src/source_generator/simple.go b/config/config_parser/src/source_generator/simple.go
index a3310d4..bd867a9 100644
--- a/config/config_parser/src/source_generator/simple.go
+++ b/config/config_parser/src/source_generator/simple.go
@@ -14,18 +14,18 @@
)
// Outputs the serialized proto.
-func BinaryOutput(c *config.CobaltConfig) (outputBytes []byte, err error) {
+func BinaryOutput(_, filtered *config.CobaltConfig) (outputBytes []byte, err error) {
buf := proto.Buffer{}
buf.SetDeterministic(true)
- if err := buf.Marshal(c); err != nil {
+ if err := buf.Marshal(filtered); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
// Outputs the serialized proto base64 encoded.
-func Base64Output(c *config.CobaltConfig) (outputBytes []byte, err error) {
- configBytes, err := BinaryOutput(c)
+func Base64Output(c, filtered *config.CobaltConfig) (outputBytes []byte, err error) {
+ configBytes, err := BinaryOutput(c, filtered)
if err != nil {
return outputBytes, err
}
diff --git a/config/config_parser/src/source_generator/source_generator_test.go b/config/config_parser/src/source_generator/source_generator_test.go
index b54b55d..02f7e09 100644
--- a/config/config_parser/src/source_generator/source_generator_test.go
+++ b/config/config_parser/src/source_generator/source_generator_test.go
@@ -14,6 +14,7 @@
"strings"
"testing"
+ "github.com/golang/protobuf/proto"
"github.com/google/go-cmp/cmp"
)
@@ -158,19 +159,34 @@
goldenFile string
cobalt_version config_parser.CobaltVersion
formatter OutputFormatter
+ hideOnClient bool
}{
- {v0ProjectConfigYaml, "golden_v0.cb.h", config_parser.CobaltVersion0, CppOutputFactory("config", []string{"a", "b"})},
- {v1ProjectConfigYaml, "golden_v1.cb.h", config_parser.CobaltVersion1, CppOutputFactory("config", []string{})},
- {v0ProjectConfigYaml, "golden_v0.cb.dart", config_parser.CobaltVersion0, DartOutputFactory("config")},
- {v1ProjectConfigYaml, "golden_v1.cb.dart", config_parser.CobaltVersion1, DartOutputFactory("config")},
- {v0ProjectConfigYaml, "golden_v0.cb.rs", config_parser.CobaltVersion0, RustOutputFactory("config", []string{"a", "b"})},
- {v1ProjectConfigYaml, "golden_v1.cb.rs", config_parser.CobaltVersion1, RustOutputFactory("config", []string{})},
+ {v0ProjectConfigYaml, "golden_v0.cb.dart", config_parser.CobaltVersion0, DartOutputFactory("config"), false},
+ {v0ProjectConfigYaml, "golden_v0.cb.h", config_parser.CobaltVersion0, CppOutputFactory("config", []string{"a", "b"}), false},
+ {v0ProjectConfigYaml, "golden_v0.cb.rs", config_parser.CobaltVersion0, RustOutputFactory("config", []string{"a", "b"}), false},
+
+ {v0ProjectConfigYaml, "golden_v0_filtered.cb.dart", config_parser.CobaltVersion0, DartOutputFactory("config"), true},
+ {v0ProjectConfigYaml, "golden_v0_filtered.cb.h", config_parser.CobaltVersion0, CppOutputFactory("config", []string{"a", "b"}), true},
+ {v0ProjectConfigYaml, "golden_v0_filtered.cb.rs", config_parser.CobaltVersion0, RustOutputFactory("config", []string{"a", "b"}), true},
+
+ {v1ProjectConfigYaml, "golden_v1.cb.dart", config_parser.CobaltVersion1, DartOutputFactory("config"), false},
+ {v1ProjectConfigYaml, "golden_v1.cb.h", config_parser.CobaltVersion1, CppOutputFactory("config", []string{}), false},
+ {v1ProjectConfigYaml, "golden_v1.cb.rs", config_parser.CobaltVersion1, RustOutputFactory("config", []string{}), false},
+
+ {v1ProjectConfigYaml, "golden_v1_filtered.cb.dart", config_parser.CobaltVersion1, DartOutputFactory("config"), true},
+ {v1ProjectConfigYaml, "golden_v1_filtered.cb.h", config_parser.CobaltVersion1, CppOutputFactory("config", []string{}), true},
+ {v1ProjectConfigYaml, "golden_v1_filtered.cb.rs", config_parser.CobaltVersion1, RustOutputFactory("config", []string{}), true},
}
func TestPrintConfig(t *testing.T) {
for _, tt := range cfgTests {
c := getConfigFrom(tt.yaml, tt.cobalt_version)
- configBytes, err := tt.formatter(&c)
+ filtered := proto.Clone(&c).(*config.CobaltConfig)
+ if tt.hideOnClient {
+ config_parser.FilterHideOnClient(filtered)
+ }
+
+ configBytes, err := tt.formatter(&c, filtered)
if err != nil {
t.Errorf("Error generating file: %v", err)
}
diff --git a/config/config_parser/src/source_generator/source_generator_test_files/golden_v0_filtered.cb.dart b/config/config_parser/src/source_generator/source_generator_test_files/golden_v0_filtered.cb.dart
new file mode 100644
index 0000000..f1ec8f3
--- /dev/null
+++ b/config/config_parser/src/source_generator/source_generator_test_files/golden_v0_filtered.cb.dart
@@ -0,0 +1,20 @@
+// This file was generated by Cobalt's Config parser based on the configuration
+// YAML in the cobalt_config repository. Edit the YAML there to make changes.
+// Metric ID Constants
+// Daily rare event counts
+// ignore: constant_identifier_names
+const int dailyRareEventCountsMetricId = 1;
+// Module views
+// ignore: constant_identifier_names
+const int moduleViewsMetricId = 2;
+
+// Report ID Constants
+// Fuchsia Ledger Daily Rare Events
+// ignore: constant_identifier_names
+const int fuchsiaLedgerDailyRareEventsReportId = 1;
+// Fuchsia Module Daily Launch Counts
+// ignore: constant_identifier_names
+const int fuchsiaModuleDailyLaunchCountsReportId = 2;
+
+// The base64 encoding of the bytes of a serialized CobaltConfig proto message.
+const String config = 'CmUIChAFGAEyXRUAAIA/OlYKDkxlZGdlci1zdGFydHVwCh1Db21taXRzLXJlY2VpdmVkLW91dC1vZi1vcmRlcgoOQ29tbWl0cy1tZXJnZWQKFU1lcmdlZC1jb21taXRzLW1lcmdlZAoMCAoQBRgCIgQIAhACEpgBCAoQBRgBIhdEYWlseSByYXJlIGV2ZW50IGNvdW50cypJRGFpbHkgY291bnRzIG9mIHNldmVyYWwgZXZlbnRzIHRoYXQgYXJlIGV4cGVjdGVkIHRvIG9jY3VyIHJhcmVseSBpZiBldmVyLjIqCgpFdmVudCBuYW1lEhwKGldoaWNoIHJhcmUgZXZlbnQgb2NjdXJyZWQ/OAISfQgKEAUYAiIMTW9kdWxlIHZpZXdzKjVUcmFja3MgZWFjaCBpbmNpZGVuY2Ugb2Ygdmlld2luZyBhIG1vZHVsZSBieSBpdHMgVVJMLjIuCgN1cmwSJwolVGhlIFVSTCBvZiB0aGUgbW9kdWxlIGJlaW5nIGxhdW5jaGVkLjgCGqQBCAoQBRgBIiBGdWNoc2lhIExlZGdlciBEYWlseSBSYXJlIEV2ZW50cyo8QSBkYWlseSByZXBvcnQgb2YgZXZlbnRzIHRoYXQgYXJlIGV4cGVjdGVkIHRvIGhhcHBlbiByYXJlbHkuMAFCDAoKRXZlbnQgbmFtZVICEANaKAoAEiQKImZ1Y2hzaWEtY29iYWx0LXJlcG9ydHMtcDItdGVzdC1hcHAaoAEIChAFGAIiIkZ1Y2hzaWEgTW9kdWxlIERhaWx5IExhdW5jaCBDb3VudHMqPUEgZGFpbHkgcmVwb3J0IG9mIHRoZSBkYWlseSBjb3VudHMgb2YgbW9kdWxlIGxhdW5jaGVzIGJ5IFVSTC4wAkIFCgN1cmxSAhADWigKABIkCiJmdWNoc2lhLWNvYmFsdC1yZXBvcnRzLXAyLXRlc3QtYXBw';
diff --git a/config/config_parser/src/source_generator/source_generator_test_files/golden_v0_filtered.cb.h b/config/config_parser/src/source_generator/source_generator_test_files/golden_v0_filtered.cb.h
new file mode 100644
index 0000000..810b0bb
--- /dev/null
+++ b/config/config_parser/src/source_generator/source_generator_test_files/golden_v0_filtered.cb.h
@@ -0,0 +1,22 @@
+// This file was generated by Cobalt's Config parser based on the configuration
+// YAML in the cobalt_config repository. Edit the YAML there to make changes.
+#pragma once
+
+namespace a {
+namespace b {
+// Metric ID Constants
+// Daily rare event counts
+const uint32_t kDailyRareEventCountsMetricId = 1;
+// Module views
+const uint32_t kModuleViewsMetricId = 2;
+
+// Report ID Constants
+// Fuchsia Ledger Daily Rare Events
+const uint32_t kFuchsiaLedgerDailyRareEventsReportId = 1;
+// Fuchsia Module Daily Launch Counts
+const uint32_t kFuchsiaModuleDailyLaunchCountsReportId = 2;
+
+// The base64 encoding of the bytes of a serialized CobaltConfig proto message.
+const char kConfig[] = "CmUIChAFGAEyXRUAAIA/OlYKDkxlZGdlci1zdGFydHVwCh1Db21taXRzLXJlY2VpdmVkLW91dC1vZi1vcmRlcgoOQ29tbWl0cy1tZXJnZWQKFU1lcmdlZC1jb21taXRzLW1lcmdlZAoMCAoQBRgCIgQIAhACEpgBCAoQBRgBIhdEYWlseSByYXJlIGV2ZW50IGNvdW50cypJRGFpbHkgY291bnRzIG9mIHNldmVyYWwgZXZlbnRzIHRoYXQgYXJlIGV4cGVjdGVkIHRvIG9jY3VyIHJhcmVseSBpZiBldmVyLjIqCgpFdmVudCBuYW1lEhwKGldoaWNoIHJhcmUgZXZlbnQgb2NjdXJyZWQ/OAISfQgKEAUYAiIMTW9kdWxlIHZpZXdzKjVUcmFja3MgZWFjaCBpbmNpZGVuY2Ugb2Ygdmlld2luZyBhIG1vZHVsZSBieSBpdHMgVVJMLjIuCgN1cmwSJwolVGhlIFVSTCBvZiB0aGUgbW9kdWxlIGJlaW5nIGxhdW5jaGVkLjgCGqQBCAoQBRgBIiBGdWNoc2lhIExlZGdlciBEYWlseSBSYXJlIEV2ZW50cyo8QSBkYWlseSByZXBvcnQgb2YgZXZlbnRzIHRoYXQgYXJlIGV4cGVjdGVkIHRvIGhhcHBlbiByYXJlbHkuMAFCDAoKRXZlbnQgbmFtZVICEANaKAoAEiQKImZ1Y2hzaWEtY29iYWx0LXJlcG9ydHMtcDItdGVzdC1hcHAaoAEIChAFGAIiIkZ1Y2hzaWEgTW9kdWxlIERhaWx5IExhdW5jaCBDb3VudHMqPUEgZGFpbHkgcmVwb3J0IG9mIHRoZSBkYWlseSBjb3VudHMgb2YgbW9kdWxlIGxhdW5jaGVzIGJ5IFVSTC4wAkIFCgN1cmxSAhADWigKABIkCiJmdWNoc2lhLWNvYmFsdC1yZXBvcnRzLXAyLXRlc3QtYXBw";
+}
+}
diff --git a/config/config_parser/src/source_generator/source_generator_test_files/golden_v0_filtered.cb.rs b/config/config_parser/src/source_generator/source_generator_test_files/golden_v0_filtered.cb.rs
new file mode 100644
index 0000000..123857f
--- /dev/null
+++ b/config/config_parser/src/source_generator/source_generator_test_files/golden_v0_filtered.cb.rs
@@ -0,0 +1,20 @@
+// This file was generated by Cobalt's Config parser based on the configuration
+// YAML in the cobalt_config repository. Edit the YAML there to make changes.
+pub mod a {
+pub mod b {
+// Metric ID Constants
+// Daily rare event counts
+pub const DAILY_RARE_EVENT_COUNTS_METRIC_ID = 1;
+// Module views
+pub const MODULE_VIEWS_METRIC_ID = 2;
+
+// Report ID Constants
+// Fuchsia Ledger Daily Rare Events
+pub const FUCHSIA_LEDGER_DAILY_RARE_EVENTS_REPORT_ID = 1;
+// Fuchsia Module Daily Launch Counts
+pub const FUCHSIA_MODULE_DAILY_LAUNCH_COUNTS_REPORT_ID = 2;
+
+// The base64 encoding of the bytes of a serialized CobaltConfig proto message.
+pub const CONFIG: &str = "CmUIChAFGAEyXRUAAIA/OlYKDkxlZGdlci1zdGFydHVwCh1Db21taXRzLXJlY2VpdmVkLW91dC1vZi1vcmRlcgoOQ29tbWl0cy1tZXJnZWQKFU1lcmdlZC1jb21taXRzLW1lcmdlZAoMCAoQBRgCIgQIAhACEpgBCAoQBRgBIhdEYWlseSByYXJlIGV2ZW50IGNvdW50cypJRGFpbHkgY291bnRzIG9mIHNldmVyYWwgZXZlbnRzIHRoYXQgYXJlIGV4cGVjdGVkIHRvIG9jY3VyIHJhcmVseSBpZiBldmVyLjIqCgpFdmVudCBuYW1lEhwKGldoaWNoIHJhcmUgZXZlbnQgb2NjdXJyZWQ/OAISfQgKEAUYAiIMTW9kdWxlIHZpZXdzKjVUcmFja3MgZWFjaCBpbmNpZGVuY2Ugb2Ygdmlld2luZyBhIG1vZHVsZSBieSBpdHMgVVJMLjIuCgN1cmwSJwolVGhlIFVSTCBvZiB0aGUgbW9kdWxlIGJlaW5nIGxhdW5jaGVkLjgCGqQBCAoQBRgBIiBGdWNoc2lhIExlZGdlciBEYWlseSBSYXJlIEV2ZW50cyo8QSBkYWlseSByZXBvcnQgb2YgZXZlbnRzIHRoYXQgYXJlIGV4cGVjdGVkIHRvIGhhcHBlbiByYXJlbHkuMAFCDAoKRXZlbnQgbmFtZVICEANaKAoAEiQKImZ1Y2hzaWEtY29iYWx0LXJlcG9ydHMtcDItdGVzdC1hcHAaoAEIChAFGAIiIkZ1Y2hzaWEgTW9kdWxlIERhaWx5IExhdW5jaCBDb3VudHMqPUEgZGFpbHkgcmVwb3J0IG9mIHRoZSBkYWlseSBjb3VudHMgb2YgbW9kdWxlIGxhdW5jaGVzIGJ5IFVSTC4wAkIFCgN1cmxSAhADWigKABIkCiJmdWNoc2lhLWNvYmFsdC1yZXBvcnRzLXAyLXRlc3QtYXBw";
+}
+}
diff --git a/config/config_parser/src/source_generator/source_generator_test_files/golden_v1_filtered.cb.dart b/config/config_parser/src/source_generator/source_generator_test_files/golden_v1_filtered.cb.dart
new file mode 100644
index 0000000..6d6dc82
--- /dev/null
+++ b/config/config_parser/src/source_generator/source_generator_test_files/golden_v1_filtered.cb.dart
@@ -0,0 +1,22 @@
+// This file was generated by Cobalt's Config parser based on the configuration
+// YAML in the cobalt_config repository. Edit the YAML there to make changes.
+// Metric ID Constants
+// the_metric_name
+// ignore: constant_identifier_names
+const int theMetricNameMetricId = 238615413;
+// the_other_metric_name
+// ignore: constant_identifier_names
+const int theOtherMetricNameMetricId = 2739731282;
+
+// Enum for the_other_metric_name (EventCode)
+class TheOtherMetricNameEventCode {
+ static const int AnEvent = 0;
+ static const int AnotherEvent = 1;
+ static const int AThirdEvent = 2;
+}
+const int TheOtherMetricNameEventCode_AnEvent = TheOtherMetricNameEventCode::AnEvent;
+const int TheOtherMetricNameEventCode_AnotherEvent = TheOtherMetricNameEventCode::AnotherEvent;
+const int TheOtherMetricNameEventCode_AThirdEvent = TheOtherMetricNameEventCode::AThirdEvent;
+
+// The base64 encoding of the bytes of a serialized CobaltConfig proto message.
+const String config = 'KqkBCghjdXN0b21lchAKGpoBCgdwcm9qZWN0EAUaTQoPdGhlX21ldHJpY19uYW1lEAoYBSD19uNxYhUKCnRoZV9yZXBvcnQQu6WL8QgYj05iGgoQdGhlX290aGVyX3JlcG9ydBDK3M3qARgGGj4KFXRoZV9vdGhlcl9tZXRyaWNfbmFtZRAKGAUg0vazmgooATjIAVABYhQKCnRoZV9yZXBvcnQQu6WL8QgYBw==';
diff --git a/config/config_parser/src/source_generator/source_generator_test_files/golden_v1_filtered.cb.h b/config/config_parser/src/source_generator/source_generator_test_files/golden_v1_filtered.cb.h
new file mode 100644
index 0000000..9eede13
--- /dev/null
+++ b/config/config_parser/src/source_generator/source_generator_test_files/golden_v1_filtered.cb.h
@@ -0,0 +1,22 @@
+// This file was generated by Cobalt's Config parser based on the configuration
+// YAML in the cobalt_config repository. Edit the YAML there to make changes.
+#pragma once
+
+// Metric ID Constants
+// the_metric_name
+const uint32_t kTheMetricNameMetricId = 238615413;
+// the_other_metric_name
+const uint32_t kTheOtherMetricNameMetricId = 2739731282;
+
+// Enum for the_other_metric_name (EventCode)
+enum class TheOtherMetricNameEventCode {
+ AnEvent = 0,
+ AnotherEvent = 1,
+ AThirdEvent = 2,
+};
+const TheOtherMetricNameEventCode TheOtherMetricNameEventCode_AnEvent = TheOtherMetricNameEventCode::AnEvent;
+const TheOtherMetricNameEventCode TheOtherMetricNameEventCode_AnotherEvent = TheOtherMetricNameEventCode::AnotherEvent;
+const TheOtherMetricNameEventCode TheOtherMetricNameEventCode_AThirdEvent = TheOtherMetricNameEventCode::AThirdEvent;
+
+// The base64 encoding of the bytes of a serialized CobaltConfig proto message.
+const char kConfig[] = "KqkBCghjdXN0b21lchAKGpoBCgdwcm9qZWN0EAUaTQoPdGhlX21ldHJpY19uYW1lEAoYBSD19uNxYhUKCnRoZV9yZXBvcnQQu6WL8QgYj05iGgoQdGhlX290aGVyX3JlcG9ydBDK3M3qARgGGj4KFXRoZV9vdGhlcl9tZXRyaWNfbmFtZRAKGAUg0vazmgooATjIAVABYhQKCnRoZV9yZXBvcnQQu6WL8QgYBw==";
diff --git a/config/config_parser/src/source_generator/source_generator_test_files/golden_v1_filtered.cb.rs b/config/config_parser/src/source_generator/source_generator_test_files/golden_v1_filtered.cb.rs
new file mode 100644
index 0000000..e7f40e1
--- /dev/null
+++ b/config/config_parser/src/source_generator/source_generator_test_files/golden_v1_filtered.cb.rs
@@ -0,0 +1,17 @@
+// This file was generated by Cobalt's Config parser based on the configuration
+// YAML in the cobalt_config repository. Edit the YAML there to make changes.
+// Metric ID Constants
+// the_metric_name
+pub const THE_METRIC_NAME_METRIC_ID = 238615413;
+// the_other_metric_name
+pub const THE_OTHER_METRIC_NAME_METRIC_ID = 2739731282;
+
+// Enum for the_other_metric_name (EventCode)
+pub enum TheOtherMetricNameEventCode {
+ AnEvent = 0,
+ AnotherEvent = 1,
+ AThirdEvent = 2,
+}
+
+// The base64 encoding of the bytes of a serialized CobaltConfig proto message.
+pub const CONFIG: &str = "KqkBCghjdXN0b21lchAKGpoBCgdwcm9qZWN0EAUaTQoPdGhlX21ldHJpY19uYW1lEAoYBSD19uNxYhUKCnRoZV9yZXBvcnQQu6WL8QgYj05iGgoQdGhlX290aGVyX3JlcG9ydBDK3M3qARgGGj4KFXRoZV9vdGhlcl9tZXRyaWNfbmFtZRAKGAUg0vazmgooATjIAVABYhQKCnRoZV9yZXBvcnQQu6WL8QgYBw==";
diff --git a/config/config_parser/src/source_generator/source_outputter.go b/config/config_parser/src/source_generator/source_outputter.go
index 54e8712..5a0701c 100644
--- a/config/config_parser/src/source_generator/source_outputter.go
+++ b/config/config_parser/src/source_generator/source_outputter.go
@@ -28,7 +28,7 @@
writeStringConstant(so *sourceOutputter, value string, name ...string)
}
-type OutputFormatter func(c *config.CobaltConfig) (outputBytes []byte, err error)
+type OutputFormatter func(c, filtered *config.CobaltConfig) (outputBytes []byte, err error)
type sourceOutputter struct {
buffer *bytes.Buffer
@@ -186,7 +186,7 @@
return nil
}
-func (so *sourceOutputter) writeFile(c *config.CobaltConfig) error {
+func (so *sourceOutputter) writeFile(c, filtered *config.CobaltConfig) error {
so.writeGenerationWarning()
so.language.writeExtraHeader(so)
@@ -201,7 +201,7 @@
so.writeLegacyConstants(c)
}
- b64Bytes, err := Base64Output(c)
+ b64Bytes, err := Base64Output(c, filtered)
if err != nil {
return err
}
@@ -217,8 +217,8 @@
}
func (so *sourceOutputter) getOutputFormatter() OutputFormatter {
- return func(c *config.CobaltConfig) (outputBytes []byte, err error) {
- err = so.writeFile(c)
+ return func(c, filtered *config.CobaltConfig) (outputBytes []byte, err error) {
+ err = so.writeFile(c, filtered)
return so.Bytes(), err
}
}
diff --git a/config/metric_definition.proto b/config/metric_definition.proto
index 52a51b7..9419ded 100644
--- a/config/metric_definition.proto
+++ b/config/metric_definition.proto
@@ -7,6 +7,7 @@
import "config/metrics.proto";
import "config/report_definition.proto";
+import "config/annotations.proto";
option go_package = "config";
@@ -187,12 +188,11 @@
//
// This field is used in most Metric types.
//
- // The keys are the numeric codes and the values are the human-readable
- // labels for the codes. It is OK to add new elements to this map or to change
- // the spelling of labels after data collection has started. It is not OK to
+ // The keys are the numeric codes and the values are the human-readable labels
+ // for the codes. It is OK to add new elements to this map or to change the
+ // spelling of labels after data collection has started. It is not OK to
// change the meaning of any of the codes.
- // ##DO_NOT_POPULATE_ON_CLIENT##
- map<uint32, string> event_codes = 6;
+ map<uint32, string> event_codes = 6 [(cobalt_options).hide_on_client = true];
// Only needed with Metrics of type EVENT_OCCURRED.
// While additional event_codes may be added after data collection has begun,
@@ -232,12 +232,12 @@
//
// The date must be expressed in yyyy/mm/dd form.
// It may be at most one year in the future.
- string expiration_date = 1;
+ string expiration_date = 1 [(cobalt_options).hide_on_client = true];
// Primary contacts for questions/bugs regarding this metric (may be a
// group). This should be a fully qualified email address (e.g.
// my-group@test.com)
- repeated string owner = 2;
+ repeated string owner = 2 [(cobalt_options).hide_on_client = true];
// Maximum ReleaseStage for which this Metric is allowed to be collected.
ReleaseStage max_release_stage = 4;
diff --git a/config/report_definition.proto b/config/report_definition.proto
index a33e2fe..5ef43cf 100644
--- a/config/report_definition.proto
+++ b/config/report_definition.proto
@@ -8,6 +8,7 @@
import "config/metrics.proto";
import "config/report_configs.proto";
import "config/window_size.proto";
+import "config/annotations.proto";
option go_package = "config";
@@ -416,8 +417,7 @@
// should be used, not both. Used for the hashed |component_name|
// field for several Report types and the encoded |string| field for the
// HIGH_FREQUENCY_STRING_COUNTS Report type.
- // ##DO_NOT_POPULATE_ON_CLIENT##
- repeated string candidate_list = 8;
+ repeated string candidate_list = 8 [(cobalt_options).hide_on_client = true];
// Simple name or full path to file containing known string values.
// Either this or |candidate_list| should be used, not both. Used for the