This document describes the client side API for defining and recording Structured Metrics and CrOS Events. Structured Metrics is supported on ChromeOS, Windows, Mac, and Linux. ChromeOS support includes Ash Chrome, and Platform2 processes.
This is not a technical document.
A single element of Structured Metrics is called an Event. These events are defined as a part of a project. Each project is self contained and the events of different projects are unable to be correlated.
Below are the initial steps that much be take before implementation for Structured Metrics and CrOS Events.
Projects and Events are declared in //tools/metrics/structured/sync/structured.xml.
name attribute. All names must be in CamelCase as they are used directly for code generation.owner element, multiple are allowed.id element, valid values: project and none. When value is project then a unique id determined per-project. When value is none the an unique id is not assigned for the events of this project.scope element, valid values: profile and device. When value is profile then the unique id is determined per-profile and per-profile. When value is device then the unique id is determined per-device and per-profile. If id is none this element has no meaning. Currently, Windows, Mac, and Linux only support device scope. Scope is not applicable to projects in the ChromiumOS repository.key-rotation element. The key rotation describes how often the key used to generate the id is rotated to a new value. E.G. If the key rotations value is 90 then every 90 days the key will be changed resulting in new id's.summary element. This will be used to describe the purpose of the project and when an event is recorded.chromium. If the target webui is added, the project will also generate code to be used in WebUI's Renderer process (i.e. Typescript).<project name="Navigation" targets="chromium,webui"> <owner>navigator1@chromium.com</owner> <owner>navigation-team@google.com</owner> <id>project</id> <scope>device</scope> <key-rotation>90</key-rotation> <summary> Users navigation within a page. </summary> <!--Events--> </project>
name attribute.force_record which allows for events to be recorded if UMA is not consented. If you think your use-case needs this functionality contact OWNERs.summary element.metric elements. Each metric must have a name attribute and type attribute. Valid types are: hmac-string, raw-string, int, double, int-array, and project defined Enum. int-array metric type has an additional attribute called max which is the max length of the integer array.An enum can be defined that can be used by all events of the project it was defined. Multiple enums can be defined per-project. It is recommended that the first element is a reasonable default. The syntax is defined in the Event Examples section.
<project name="Navigation"> <!--Project Metadata--> <enum name="Direction"> <variant value="0">None</variant> <variant value="1">Forward</variant> <variant value="3">Back</variant> </enum> <event name="PageTransition"> <summary> Captures when a user transitions page. </summary> <metric name="PageId" type="int"> <summary> The source page of transition. </summary> <metric> <metric name="TransitionDirection" type="Direction"> <summary> The direction of the transition. </summary> <metric> </event> <event name="Impression"> <summary> Impression of the transition. </summary> <metric name="ElementIds" type="int-array" max="10"> <summary> Elements of source page. </summary> </metric> </event> </project>
CrOS Event's is a part of Structured Metrics which provides sequencing information at the time the event was recorded. This allows for events to be sequenced. We use a proxy for timestamp which is the reset id and system uptime. Reset id is manually managed when the device boots.
To declare events to be used in CrOS Events they must be declared in the CrOSEvents project. The name of each event must be <UseCase>.<EventName>, e.g. AppDiscovery.AppInstalled.
We are working on an alternative method for declaring CrOS Events projects that is more scalable and easier to maintain.
By default, all projects in structured.xml will be built for the chromium target, meaning each event in the project will have an Event API generated in C++.
At build time, a C++ API is generated from the xml. The project name will become the namespace (navigation) and the event name is the event's class name (PageTransition). Each metric has a setter method in the format Set<MetricName> (SetPageId). There are l-value and r-value versions for each metric method.
In order to record an event the StructuredMetricsClient singleton is needed, defined in //components/metrics/structured/structured_metrics_client.h.
Recording can be done by:
#include "components/metrics/structured/structured_metrics_client.h" // for StructuredMetricsClient #include "components/metrics/structured/structured_events.h" // for event definitions // Shorten the namespace if desired. using nav = metrics::structured::v2::navigation; ms::StructuredMetricsClient::Record( nav::PageTransition() .SetPageId(page_id) .SetTransitionDirection(nav::Direction::Forward));
When a project is given a target of webui, they will have an Event API for each event, generated in Typescript, meant to be used for WebUI. The events are sent from the Renderer process to the Browser process using Mojo. Additionally, there is a recording API that can be used to record the event.
At build time, a Typescript API is generated from the xml for each event. Each event will generate a builder class in Typescript. Using the same example for the C++ Event API, we will get the following:
<ProjectName>_<EventName>, e.g. Navigation_PageTransitionsetPageId() and setTransitionDirection()build() methodEnums are declared at the top level in the generated structured_events.ts file. In the above example, we will then get an enum declared like:
export enum Navigation_Direction { None = 0, Forward = 1, Back = 3 };
recorded_time_since_bootSince it is not possible to obtain the system uptime when recording the event in Typescript, the system uptime is inferred using the event timestamp, used in the following equation:
event_system_uptime = browser_system_uptime - (browser_timestamp - event_timestamp)
In order to record an event, the recordStructuredEvent() function exported by chrome://resources/ash/common/metrics/structured_metrics_service.js can be used. It will create the required instance of the StructuredMetricsServiceInterface, which is the Mojo interface.
Creating an event and recording it would then look like:
import {recordStructuredEvent} from 'chrome://resources/ash/common/metrics/structured_metrics_service.js'; import * as StructuredEvents from 'chrome://resources/ash/common/metrics/structured_events.js'; // Construct the event. let structured_event: any = new StructuredEvents.Navigation_PageTransition() .setPageId(page_id) .setTransitionDirection( StructuredEvents.Navigation_Direction.Forward) .build(); // Record the event. recordStructuredEvent(structured_event);
Structured Metrics has a debug page at chrome://metrics-internals/structured that can be used to verify recorded events and their contents. The page must be manually refreshed to see recently recorded events.