1// Copyright 2023 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//      http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14syntax = "proto3";
15
16package cobalt;
17
18option java_multiple_files = true;
19option java_package = "com.google.cobalt";
20
21////////////////////////////////////////////////////////////////////////////////
22// NOTE: This file is used by the Cobalt client and the Cobalt servers.
23// The source-of-truth of this file is located in Cobalt's open source code
24// repository, and the file is copied to Android where it is used by the Cobalt
25// client. Do not edit the copy of this file in this Android repo as those edits
26// will be overwritten when the file is next copied.
27////////////////////////////////////////////////////////////////////////////////
28
29// An Observation is a piece of data sent from a Cobalt client to the Cobalt
30// server as input to a Report.
31//
32// Observations are associated with a specific Metric. They are built on a
33// Fuchsia client based on the Events logged for that Metric. Observations are
34// associated with a specific Report. They are built for the purpose of
35// generating that Report. They are transmitted from the Fuchsia client to
36// the Cobalt server where they are aggregated and analyzed in order to generate
37// the Report.
38//
39// Observations may store their data using special privacy-preserving encodings.
40// The specification of how to do this is part of the definition of a Report.
41// Observations are built for a particular Report and so use an encoding
42// appropriate for that Report.
43//
44// There are different types of Observations that are appropriate for different
45// types of Metrics and different types of Reports.
46//
47// An Observation is always transmitted and stored along with
48// some ObservationMetadata that describes, among other things, which Metric
49// and which Report it is for and on which day the Observation was formed.
50//
51// Observations are transmitted from the client to the server encrypted, inside
52// the |ciphertext| field of an EncryptedMessage. Many encrypted Observations
53// are transmitted together inside of an ObservationBatch.
54message Observation {
55  // Next observation_type ID: 9
56  // Next general ID: 1002;
57  reserved 1, 2, 3, 4, 5, 6, 7, 8, 1000;
58
59  // An Observation has one of the following types.
60  oneof observation_type {
61    SumAndCountObservation sum_and_count = 9;
62    IntegerObservation integer = 10;
63    IndexHistogramObservation index_histogram = 11;
64    StringHistogramObservation string_histogram = 12;
65    PrivateIndexObservation private_index = 13;
66    ReportParticipationObservation report_participation = 10000;
67  }
68
69  // A quasi-unique identifier for this observation. This is randomly generated
70  // on the client and used on the server as part of a fully-unique identifier.
71  // This field allows the operation of sending an Observation to the Cobalt
72  // server to be idempotent: If the same Observation is transmitted twice then
73  // the server will store the observation only once.
74  bytes random_id = 1001;
75}
76
77// Observations of type SumAndCountObservation contain one or more triples of
78// event vectors, a signed integer recording a sum and an unsigned integer
79// recording a count.
80//
81// This type of observation is used only for the FLEETWIDE_MEANS report type.
82message SumAndCountObservation {
83  message SumAndCount {
84    // Event vector to which the sum and count are associated.
85    repeated uint32 event_codes = 1;
86
87    // The device-level sum.
88    sint64 sum = 2;
89
90    // the device-level count.
91    uint64 count = 3;
92  }
93
94  repeated SumAndCount sums_and_counts = 1;
95}
96
97// Observations of type IntegerObservation contain one or more pairs of
98// event vectors and signed integers.
99//
100// This type of observation is used for the following report types:
101// FLEETWIDE_OCCURRENCE_COUNTS
102// HOURLY_VALUE_NUMERIC_STATS
103// HOURLY_VALUE_HISTOGRAMS
104// UNIQUE_DEVICE_COUNTS
105// UNIQUE_DEVICE_NUMERIC_STATS
106// UNIQUE_DEVICE_HISTOGRAMS
107message IntegerObservation {
108  message Value {
109    // Event vector to which the value is associated.
110    repeated uint32 event_codes = 1;
111
112    // The value depends upon the report type.
113    //
114    // FLEETWIDE_OCCURRENCE_COUNTS
115    // Device-level count of events with the associated event vector.
116    // Value is between 0 and the configured maximum count (inclusive).
117    //
118    // UNIQUE_DEVICE_COUNTS
119    // 1 if the associated event vector was observed.
120    //
121    // HOURLY_VALUE_NUMERIC_STATS
122    // UNIQUE_DEVICE_NUMERIC_STATS
123    // HOURLY_VALUE_HISTOGRAMS
124    // UNIQUE_DEVICE_HISTOGRAMS
125    // Device-level aggregate value for the associated event vector.
126    sint64 value = 2;
127  }
128
129  repeated Value values = 1;
130}
131
132// IndexHistogram represents a list of counts for each bucket of a histogram
133// associated with a particular event vector.
134message IndexHistogram {
135  // Event vector to which the histogram is associated.
136  repeated uint32 event_codes = 1;
137
138  // bucket_counts[i] is the count for the bucket_indices[i]th index in the
139  // histogram.
140  repeated uint32 bucket_indices = 2;
141  repeated sint64 bucket_counts = 3;
142}
143
144// Observations of type IndexHistogramObservation contain one or more pairs of
145// event vectors and lists of bucket counts.
146//
147// This type of observation is used with the FLEETWIDE_HISTOGRAMS report type.
148message IndexHistogramObservation {
149  repeated IndexHistogram index_histograms = 1;
150}
151
152// Observations of the type StringHistogramObservation contain a list of strings
153// mapping string hashes to indices and one or more pairs of event vectors
154// and lists of bucket counts.
155//
156// This type of observation is used for the following report types:
157// STRING_COUNTS
158// UNIQUE_DEVICE_STRING_COUNTS
159message StringHistogramObservation {
160  // TODO(b/322409910): Delete string_hashes after clients stop sending
161  // the field.
162  repeated bytes string_hashes = 1 [deprecated = true];
163
164  // List of hashes of strings (hashed using Farmhash Fingerprint64).
165  // The string that hashes to the bytes value in the ith position in
166  // |string_hashes| corresponds to the bucket with index i in each of the
167  // |bucket_indices| values in |string_histograms|.
168  //
169  // Only one of `string_hashes` or `string_hashes_ff64` should be used.
170  repeated bytes string_hashes_ff64 = 3;
171
172  repeated IndexHistogram string_histograms = 2;
173}
174
175// An observation of type PrivateIndexObservation contains a single integer.
176// Observations of this type are produced by the PrivacyEncoder: given a single
177// Observation of some other type, the PrivacyEncoder outputs one or more
178// PrivateIndexObservations. All data for reports with a nontrivial
179// privacy mechanism will be transported from client to server in the form of
180// PrivateIndexObservations.
181//
182// The field |index| of a PrivateIndexObservation is an index into an
183// enumeration of the set of possible Observations of another type (after
184// bucketing some parameters, as specified in the ReportDefinition for which the
185// Observation was generated.) The details of this enumeration depend on the
186// type of Observation which was given to the PrivacyEncoder.
187message PrivateIndexObservation {
188  uint64 index = 1;
189}
190
191// A pair consisting of a bucket index and a count. Each bucket is
192// an integer range. The definition of the buckets and their indices
193// is given in the MetricDefinition.
194// TODO(b/262785064): don't use this for the public LoggerInterface.
195message HistogramBucket {
196  // The index of one of the buckets.
197  uint32 index = 1;
198  // The count for that bucket.
199  uint64 count = 2;
200}
201
202// Observations of this type are used to signal that a given device was
203// collecting data for a given report, over some window of time. This
204// Observation type has no required fields.
205//
206// ReportParticipationObservations are produced by the PrivacyEncoder and
207// consumed by the ReportGenerator for reports that use local differential
208// privacy.
209message ReportParticipationObservation {}
210