tree: dd9e06efc5d13636e6eab753fdbe29d18c5ffd87 [path history] [tgz]
  1. source_generator_test_files/
  2. cpp.go
  3. dart.go
  4. dep.go
  5. dep_test.go
  6. go.go
  7. ident.go
  8. ident_test.go
  9. java.go
  10. json.go
  11. json_test.go
  12. README.md
  13. rust.go
  14. simple.go
  15. source_generator_test.go
  16. source_outputter.go
  17. source_outputter_test.go
  18. utils.go
  19. utils_test.go
  20. writer.go
src/bin/config_parser/src/source_generator/README.md

Cobalt Registry Source Generator

This code generates source files for C++, Dart, and Rust to facilitate interacting with the Cobalt API in those languages.

What this generator outputs

The Source Generator writes out constants for all customer ids, project ids, metric ids, and report ids for the selected config. It will output these constants with names that match the language's standard global constant naming convention. (e.g. C++ uses kCamelCase, and rust uses UPPER_SNAKE_CASE) Additionally, it generates enums for all of the event_codes. If a metric_definition looked like the following:

- id: 1
  metric_name: "A Metric"
  metric_dimensions:
    - dimension: "A Dimension"
      event_codes:
        0: "An Event"
        1: "Another Event"
        2: "A Third Event"
    - dimension: "Second Dimension"
      event_codes:
        1: "Occurred"

It would generate enums for each of the metric_dimensions, and (if there is more than 1 metric_dimension), it will generate a helper struct to make handling groups of event_codes easier:

In C++ it would generate:

enum AMetricMetricDimensionADimension {
  AnEvent = 0,
  AnotherEvent = 1,
  AThirdEvent = 2,
}

enum AMetricMetricDimensionSecondDimension {
  Occurred = 1,
}

struct AMetricEventCodes {
  AMetricMetricDimensionADimension a_dimension;
  AMetricMetricDimensionSecondDimension second_dimension;

  [[nodiscard]] std::vector<uint32_t> ToVector() const {
    return {
      a_dimension,
      second_dimension,
    };
  }
};

And the following in Rust:

pub enum AMetricMetricDimensionADimension {
  AnEvent = 0,
  AnotherEvent = 1,
  AThirdEvent = 2,
}

pub enum AMetricMetricDimensionSecondDimension {
  Occurred = 1,
}

pub struct AMetricEventCodes {
  pub a_dimension: AMetricMetricDimensionADimension,
  pub second_dimension: AMetricMetricDimensionSecondDimension,
}

impl AsEventCodes for AMetricEventCodes {
  fn as_event_codes(&self) -> Vec<u32> {
    use cobalt_client::traits::AsEventCode;
    vec![
      self.a_dimension.as_event_code(),
      self.second_dimension.as_event_code(),
    ]
  }
}

And the following in Dart:

class AMetricMetricDimensionADimension {
  static const int AnEvent = 0;
  static const int AnotherEvent = 1;
  static const int AThirdEvent = 2;
}

class AMetricMetricDimensionSecondDimension {
  static const int Occurred = 1;
}

class AMetricEventCodes {
  int a_dimension;
  int second_dimension;

  List<int> toList() {
    return [
      a_dimension,
      second_dimension,
    ];
  }
}

And the following in Go:

type AMetricMetricDimensionADimension uint32
const (
  AMetricMetricDimensionADimension = iota
  AnEvent = 0
  AnotherEvent = 1
  AThirdEvent = 2
)

type AMetricMetricDimensionSecondDimension uint32
const (
  AMetricMetricDimensionSecondDimension = iota
  Occurred = 1
)

type AMetricEventCodes struct {
  AMetricMetricDimensionADimension a_dimension;
  AMetricMetricDimensionSecondDimension second_dimension;
}

func (s AMetricEventCodes) ToArray() []uint32 {
  return []uint32{
    s.a_dimension,
    s.second_dimension,
  }
}

EventCodes struct

The *EventCodes struct that is generated is useful for metrics that have more than 1 MetricDimension. It helps have a single structured object that can hold all of the field values in one place, and makes sure that the event codes are serialized into the event_codes array in the correct order.

For example, in c++, rather than having a method like:

void LogOccurrence(const std::vector<uint32_t> &event_codes);

that could call down to the logger like:

logger.LogOccurrence(MetricId, event_codes, ...);

You could instead use the EventCodes struct like the following:

void LogOccurrence(const AMetricEventCodes &event_codes);

that could call down to the logger like:

logger.LogOccurrence(MetricId, event_codes.ToArray(), ...);

The advantage of this method is that there is no way the event_codes will be passed down in the wrong order, and it's all type checked.

For more examples of what would be outputted, see the files under the source_generator_test_files directory.

For testing

The source generator outputs a few extra things for use in testing cobalt. These include:

  • ReportIds.
  • metric/report indices
    • These indices are the index of the associated metric/report in the registry proto array. These can be used to look up metrics/reports without needing an external ID index.