| # Copyright 2024 The Chromium Authors |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| """Abstract class definition of Code Generation from structured.xml |
| into definitions for different targets.""" |
| |
| from abc import ABC, abstractmethod |
| from codegen_util import Util |
| |
| # Default target if not explicitly specified in the XML. |
| DEFAULT_TARGET = "chromium" |
| |
| |
| class EventTemplateBase(ABC): |
| """EventTemplate is a base abstract class, which contains the common |
| abstract methods and common constructor to generate code for |
| structured events.""" |
| |
| def __init__(self, model, dirname, basename, file_template, project_template, |
| enum_template, event_template, metric_template): |
| self.model = model |
| self.dirname = dirname |
| self.basename = basename |
| self.file_template = file_template |
| self.project_template = project_template |
| self.event_template = event_template |
| self.enum_template = enum_template |
| self.metric_template = metric_template |
| |
| @abstractmethod |
| def write_file(self): |
| pass |
| |
| |
| class ProjectInfoBase(ABC): |
| """Codegen-related info about a Structured Metrics project. |
| Constructor takes in a set of target_names in order to determine |
| whether a project should have its code generated.""" |
| |
| def __init__(self, project, target_names): |
| self.name = Util.sanitize_name(project.name) |
| self.namespace = Util.camel_to_snake(self.name) |
| self.name_hash = Util.hash_name(self.name) |
| self.events = project.events |
| self.enums = project.enums |
| self.targets = project.targets |
| self.target_names = target_names |
| self.platform = project.platform |
| |
| # Set ID type. |
| if project.id == 'uma': |
| self.id_type = 'kUmaId' |
| elif project.id == 'per-project': |
| self.id_type = 'kProjectId' |
| elif project.id == 'none': |
| self.id_type = 'kUnidentified' |
| else: |
| raise ValueError('Invalid id type.') |
| |
| # Set ID scope |
| if project.scope == 'profile': |
| self.id_scope = 'kPerProfile' |
| elif project.scope == 'device': |
| self.id_scope = 'kPerDevice' |
| else: |
| raise ValueError('Invalid id scope.') |
| |
| # Set event type. This is inferred by checking all metrics within the |
| # project. If any of a project's metrics is a raw string, then its events |
| # are considered raw string events, even if they also contain non-strings. |
| self.event_type = 'REGULAR' |
| for event in project.events: |
| for metric in event.metrics: |
| if metric.type == 'raw-string': |
| self.event_type = 'RAW_STRING' |
| break |
| |
| # Check if event is part of an event sequence. Note that this goes after the |
| # raw string check since the type has higher priority. |
| if project.is_event_sequence_project: |
| self.is_event_sequence = 'true' |
| self.event_type = 'SEQUENCE' |
| else: |
| self.is_event_sequence = 'false' |
| |
| self.key_rotation_period = project.key_rotation_period |
| |
| if len(self.targets) == 0: |
| self.targets.add(DEFAULT_TARGET) |
| |
| # Check if the Project should be generated for the given target. |
| self.should_codegen = False |
| for target in self.targets: |
| if target in self.target_names: |
| self.should_codegen = True |
| |
| |
| class EventInfoBase(ABC): |
| """Codegen-related info about a Structured Metrics event.""" |
| |
| def __init__(self, event, project_info): |
| self.name = Util.sanitize_name(event.name) |
| self.project_name = project_info.name |
| self.platform = project_info.platform |
| self.name_hash = Util.event_name_hash(project_info.name, self.name, |
| project_info.platform) |
| self.is_event_sequence = project_info.is_event_sequence |
| self.force_record = str(event.force_record).lower() |
| self.metrics = event.metrics |
| |
| |
| class MetricInfoBase(ABC): |
| """Codegen-related info about a Structured Metrics metric.""" |
| |
| def __init__(self, metric): |
| self.name = Util.sanitize_name(metric.name) |
| self.hash = Util.hash_name(metric.name) |
| self.is_enum = metric.is_enum |