chromium/third_party/metrics_proto/structured_data.proto

// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

syntax = "proto2";

option optimize_for = LITE_RUNTIME;
option java_package = "org.chromium.components.metrics";

package metrics;

// One structured metrics event, containing several hashed and unhashed metrics
// related to a single event type. Structured metrics have hashing keys based on
// the project. A project refers to a use-case of the framework (ie bluetooth,
// event sequence).
//
// Structured metrics is currently only used for the CrOS platform, so some of
// the fields are CrOS-specific (ie device_project_id, user_project_id). If
// structured metrics were to expand to other platforms, these fields will need
// to be revisited.
//
// Next tag: 10
message StructuredEventProto {
  // A per-client, per-profile, per-project ID that is used only for structured
  // metrics. For projects recorded from Chrome OS's platform2 repository, this
  // ID is device-wide, not per-profile. The ID is rotated at least every 90
  // days.
  //
  // For events of type SEQUENCE, the ID will be rotated every 120 days.
  optional fixed64 profile_event_id = 1;

  // A per-profile, per-project ID used only for events of type SEQUENCE. A
  // device may have multiple profiles and multiple projects (ie cros-events).
  //
  // This ID is generated by applying HMAC on a locally-generated GUID (which is
  // never sent) with a per-profile, per-project key. The first 8 bytes of the
  // resulting string will be emitted.
  //
  // For events recorded when a user is not logged in or for events recorded
  // outside of Chrome, this field should be empty.
  //
  // Since the per-profile, per-project keys are rotated every 120 days, this
  // means that the |user_project_id| will also change every N days. For more
  // details on how keys are rotated, refer to go/structured-metrics.
  optional fixed64 user_project_id = 7;

  // A device-wide, per-project ID used only for events of type SEQUENCE. This
  // ID is rotated every 120 days.
  //
  // This ID is generated by hashing a locally-generated GUID (which is never
  // sent) with a per-device, per-project key. The first 8 bytes of thee
  // resulting string will be emitted.
  //
  // Since the per-device, per-project keys are rotated every N (default 90)
  // days, this means that the |device_project_id| will also change every N
  // days. For more details on how keys are rotated, refer to
  // go/structured-metrics.
  //
  // Note that an event may have both a |device_project_id| and
  // |user_project_id|.
  optional fixed64 device_project_id = 8;

  // The first 8 bytes of the MD5 hash of the event's name as a string. Each
  // name is defined in src/tools/metrics/structured/structured.xml, and this
  // will be the hash of one of those.
  optional fixed64 event_name_hash = 2;

  // All metric values for this event. Each metric has two properties defined in
  // structured.xml that determine what is recorded.
  //
  // 1. Metric name. This is a string, and the first 8 bytes of its MD5 hash is
  //    recorded as name_hash.
  //
  // 2. Kind. Each metric can store four kinds of values.
  //
  //    - int64. The client supplies an int64 value for the metric, and that
  //      value is recorded as-is in value_int64.
  //
  //    - string. The client supplies a string value for the metric, which is
  //      recorded as-is in value_string. This is sometimes referred to as a
  //      "raw string" to differentiate from the following.
  //
  //    - hashed-string. The client supplies an arbitrary string for the metric.
  //      The string itself is not recorded, instead, value_hmac records the
  //      first 8 bytes of:
  //
  //          HMAC_SHA256(concat(string, metric_name), event_key)
  //
  //    - double. The client supplies a double value for the metric, which is
  //      recorded as-is in value_double.
  //
  //      The event_key is a per-profile, per-client, per-project secret 32-byte
  //      key used only for signing hashed values for this event. Keys should
  //      never leave the device, and are rotated at least every 90 days.
  //
  //    - int64 array: This client supplies an array of int64 values for the
  //      metric. Each metric will have an max defined by the metric definition.
  message Metric {
    optional fixed64 name_hash = 1;

    // Wrapper of repeated integer fields.
    message RepeatedInt64 {
      repeated int64 values = 1 [packed = true];
    }

    oneof value {
      fixed64 value_hmac = 2;
      int64 value_int64 = 3;
      string value_string = 4;
      double value_double = 5;
      RepeatedInt64 value_repeated_int64 = 6;
    }
  }
  repeated Metric metrics = 3;

  // Type of this event, which determines which log source the event is saved
  // into. An event should have type RAW_STRING if and only if the event may
  // contain raw string metrics, ie. strings that have not been HMAC'd. The
  // UNKNOWN value is considered an error and should never be sent.
  //
  // An event should be marked as a SEQUENCE if it contains temporal data.
  enum EventType {
    UNKNOWN = 0;
    REGULAR = 1;
    RAW_STRING = 2;
    SEQUENCE = 3;
  }
  optional EventType event_type = 4;

  // The project name hash is the first 8 bytes of the MD5 hash of the project
  // name that is defined in src/tools/metrics/structured/structured.xml.
  optional fixed64 project_name_hash = 5;
  // These enum values represent the type of user segment for the primary
  // user.
  enum PrimaryUserSegment {
    UNKNOWN_PRIMARY_USER_TYPE = 0;
    // Primary profile is for an unmanaged user.
    UNMANAGED = 1;
    // Primary profile is for a user belonging to a K-12 EDU organization.
    K12 = 2;
    // Primary profile is for a user belonging to an university EDU
    // organization.
    UNIVERSITY = 3;
    // Primary profile is for a user belonging to a non-profit organization.
    NON_PROFIT = 4;
    // Primary profile is for a user belonging to an enterprise organization.
    ENTERPRISE_ORGANIZATION = 5;
    // Primary profile is for a kiosk app.
    KIOS_APP = 6;
    // Primary profile is for a managed guest session.
    MANAGED_GUEST_SESSION = 7;
    // Primary profile is for a Demo Mode.
    DEMO_MODE = 8;
  }

  // Metadata associated with events for which relative order in which the
  // events occur are of interest.
  //
  // Next tag: 6
  message EventSequenceMetadata {
    // GUIDs generated on the client to uniquely identify an event. These event
    // IDs will be used to establish relationships between events on the client.
    optional fixed64 event_unique_id = 1;

    // Time elapsed since boot time. Note that system uptime includes duration a
    // device has spent asleep. System uptime resets when a machine reboots.
    // Granularity is in milliseconds.
    optional int64 system_uptime = 2;

    // Monotonically increasing number incremented every time a system reset is
    // detected. This value will be reset to 0 in the event of a powerwash.
    optional int64 reset_counter = 3;

    // The number of weeks since the client id rotated.
    optional uint32 client_id_rotation_weeks = 4;

    // The segment policy of the user.
    optional PrimaryUserSegment primary_user_segment = 5;
  }

  // Metadata associated with event type SEQUENCE. This field will be stripped
  // if the event is not of type SEQUENCE.
  optional EventSequenceMetadata event_sequence_metadata = 6;
}

// The top-level proto for structured metrics. One StructuredDataProto is
// uploaded per UMA upload containing structured metrics. Contains all
// structured events for that upload, and any other metadata.
//
// Next tag: 4
message StructuredDataProto {
  repeated StructuredEventProto events = 1;

  // Whether the device is enrolled and may be controlled by a policy.
  // Deprecated as of Chrome M119, use |device_segment| to determine if the
  // device is enrolled.
  optional bool is_device_enrolled = 2 [deprecated = true];

  // The broader market segment the device is used.
  enum DeviceSegment {
    UNKNOWN = 0;
    CONSUMER = 1;
    EDUCATION = 2;
    ENTERPRISE = 3;
  }

  // The segment policy of the device.
  optional DeviceSegment device_segment = 3;
}