xref: /aosp_15_r20/external/googleapis/google/cloud/timeseriesinsights/v1/timeseries_insights.proto (revision d5c09012810ac0c9f33fe448fb6da8260d444cc9)
1// Copyright 2022 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.
14
15syntax = "proto3";
16
17package google.cloud.timeseriesinsights.v1;
18
19import "google/api/annotations.proto";
20import "google/api/client.proto";
21import "google/api/field_behavior.proto";
22import "google/api/resource.proto";
23import "google/protobuf/duration.proto";
24import "google/protobuf/empty.proto";
25import "google/protobuf/timestamp.proto";
26import "google/rpc/status.proto";
27
28option cc_enable_arenas = true;
29option go_package = "cloud.google.com/go/timeseriesinsights/apiv1/timeseriesinsightspb;timeseriesinsightspb";
30option java_multiple_files = true;
31option java_outer_classname = "TimeseriesInsightsProto";
32option java_package = "com.google.cloud.timeseriesinsights.v1";
33
34service TimeseriesInsightsController {
35  option (google.api.default_host) = "timeseriesinsights.googleapis.com";
36  option (google.api.oauth_scopes) = "https://www.googleapis.com/auth/cloud-platform";
37
38  // Lists [DataSets][google.cloud.timeseriesinsights.v1.DataSet] under the project.
39  //
40  // The order of the results is unspecified but deterministic. Newly created
41  // [DataSets][google.cloud.timeseriesinsights.v1.DataSet] will not necessarily be added to the end
42  // of this list.
43  rpc ListDataSets(ListDataSetsRequest) returns (ListDataSetsResponse) {
44    option (google.api.http) = {
45      get: "/v1/{parent=projects/*/locations/*}/datasets"
46      additional_bindings {
47        get: "/v1/{parent=projects/*}/datasets"
48      }
49    };
50    option (google.api.method_signature) = "parent";
51  }
52
53  // Create a [DataSet][google.cloud.timeseriesinsights.v1.DataSet] from data stored on Cloud
54  // Storage.
55  //
56  // The data must stay immutable while we process the
57  // [DataSet][google.cloud.timeseriesinsights.v1.DataSet] creation; otherwise, undefined outcomes
58  // might result.  For more information, see [DataSet][google.cloud.timeseriesinsights.v1.DataSet].
59  rpc CreateDataSet(CreateDataSetRequest) returns (DataSet) {
60    option (google.api.http) = {
61      post: "/v1/{parent=projects/*/locations/*}/datasets"
62      body: "dataset"
63      additional_bindings {
64        post: "/v1/{parent=projects/*}/datasets"
65        body: "dataset"
66      }
67    };
68    option (google.api.method_signature) = "parent,dataset";
69  }
70
71  // Delete a [DataSet][google.cloud.timeseriesinsights.v1.DataSet] from the system.
72  //
73  // **NOTE**: If the [DataSet][google.cloud.timeseriesinsights.v1.DataSet] is still being
74  // processed, it will be aborted and deleted.
75  rpc DeleteDataSet(DeleteDataSetRequest) returns (google.protobuf.Empty) {
76    option (google.api.http) = {
77      delete: "/v1/{name=projects/*/locations/*/datasets/*}"
78      additional_bindings {
79        delete: "/v1/{name=projects/*/datasets/*}"
80      }
81    };
82    option (google.api.method_signature) = "name";
83  }
84
85  // Append events to a `LOADED` [DataSet][google.cloud.timeseriesinsights.v1.DataSet].
86  rpc AppendEvents(AppendEventsRequest) returns (AppendEventsResponse) {
87    option (google.api.http) = {
88      post: "/v1/{dataset=projects/*/locations/*/datasets/*}:appendEvents"
89      body: "*"
90      additional_bindings {
91        post: "/v1/{dataset=projects/*/datasets/*}:appendEvents"
92        body: "*"
93      }
94    };
95    option (google.api.method_signature) = "dataset,events";
96  }
97
98  // Execute a Timeseries Insights query over a loaded
99  // [DataSet][google.cloud.timeseriesinsights.v1.DataSet].
100  rpc QueryDataSet(QueryDataSetRequest) returns (QueryDataSetResponse) {
101    option (google.api.http) = {
102      post: "/v1/{name=projects/*/locations/*/datasets/*}:query"
103      body: "*"
104      additional_bindings {
105        post: "/v1/{name=projects/*/datasets/*}:query"
106        body: "*"
107      }
108    };
109  }
110
111  // Evaluate an explicit slice from a loaded [DataSet][google.cloud.timeseriesinsights.v1.DataSet].
112  rpc EvaluateSlice(EvaluateSliceRequest) returns (EvaluatedSlice) {
113    option (google.api.http) = {
114      post: "/v1/{dataset=projects/*/locations/*/datasets/*}:evaluateSlice"
115      body: "*"
116      additional_bindings {
117        post: "/v1/{dataset=projects/*/datasets/*}:evaluateSlice"
118        body: "*"
119      }
120    };
121  }
122
123  // Evaluate an explicit timeseries.
124  rpc EvaluateTimeseries(EvaluateTimeseriesRequest) returns (EvaluatedSlice) {
125    option (google.api.http) = {
126      post: "/v1/{parent=projects/*/locations/*}/datasets:evaluateTimeseries"
127      body: "*"
128      additional_bindings {
129        post: "/v1/{parent=projects/*}/datasets:evaluateTimeseries"
130        body: "*"
131      }
132    };
133  }
134}
135
136// Mapping of BigQuery columns to timestamp, group_id and dimensions.
137message BigqueryMapping {
138  // The column which should be used as the event timestamps. If not specified
139  // 'Timestamp' is used by default. The column may have TIMESTAMP or INT64
140  // type (the latter is interpreted as microseconds since the Unix epoch).
141  string timestamp_column = 1;
142
143  // The column which should be used as the group ID (grouping events into
144  // sessions). If not specified 'GroupId' is used by default, if the input
145  // table does not have such a column, random unique group IDs are
146  // generated automatically (different group ID per input row).
147  string group_id_column = 2;
148
149  // The list of columns that should be translated to dimensions. If empty,
150  // all columns are translated to dimensions. The timestamp and group_id
151  // columns should not be listed here again. Columns are expected to have
152  // primitive types (STRING, INT64, FLOAT64 or NUMERIC).
153  repeated string dimension_column = 3;
154}
155
156// A data source consists of multiple [Event][google.cloud.timeseriesinsights.v1.Event] objects stored on
157// Cloud Storage.  Each Event should be in JSON format, with one Event
158// per line, also known as JSON Lines format.
159message DataSource {
160  // Data source URI.
161  //
162  // 1) Google Cloud Storage files (JSON) are defined in the following form.
163  // `gs://bucket_name/object_name`. For more information on Cloud Storage URIs,
164  // please see https://cloud.google.com/storage/docs/reference-uris.
165  string uri = 1;
166
167  // For BigQuery inputs defines the columns that should be used for dimensions
168  // (including time and group ID).
169  BigqueryMapping bq_mapping = 2;
170}
171
172// A collection of data sources sent for processing.
173message DataSet {
174  option (google.api.resource) = {
175    type: "timeseriesinsights.googleapis.com/Dataset"
176    pattern: "projects/{project}/datasets/{dataset}"
177    pattern: "projects/{project}/locations/{location}/datasets/{dataset}"
178  };
179
180  // DataSet state.
181  enum State {
182    // Unspecified / undefined state.
183    STATE_UNSPECIFIED = 0;
184
185    // Dataset is unknown to the system; we have never seen this dataset before
186    // or we have seen this dataset but have fully GC-ed it.
187    UNKNOWN = 1;
188
189    // Dataset processing is pending.
190    PENDING = 2;
191
192    // Dataset is loading.
193    LOADING = 3;
194
195    // Dataset is loaded and can be queried.
196    LOADED = 4;
197
198    // Dataset is unloading.
199    UNLOADING = 5;
200
201    // Dataset is unloaded and is removed from the system.
202    UNLOADED = 6;
203
204    // Dataset processing failed.
205    FAILED = 7;
206  }
207
208  // The dataset name, which will be used for querying, status and unload
209  // requests. This must be unique within a project.
210  string name = 1;
211
212  // [Data dimension names][google.cloud.timeseriesinsights.v1.EventDimension.name] allowed for this `DataSet`.
213  //
214  // If left empty, all dimension names are included. This field works as a
215  // filter to avoid regenerating the data.
216  repeated string data_names = 2;
217
218  // Input data.
219  repeated DataSource data_sources = 3;
220
221  // Dataset state in the system.
222  State state = 4;
223
224  // Dataset processing status.
225  google.rpc.Status status = 5;
226
227  // Periodically we discard dataset [Event][google.cloud.timeseriesinsights.v1.Event] objects that have
228  // timestamps older than 'ttl'.  Omitting this field or a zero value means no
229  // events are discarded.
230  google.protobuf.Duration ttl = 6;
231}
232
233// Represents an event dimension.
234message EventDimension {
235  // Dimension name.
236  //
237  // **NOTE**: `EventDimension` names must be composed of alphanumeric
238  // characters only, and are case insensitive. Unicode characters are *not*
239  // supported. The underscore '_' is also allowed.
240  string name = 1;
241
242  // Dimension value.
243  //
244  // **NOTE**: All entries of the dimension `name` must have the same `value`
245  // type.
246  oneof value {
247    // String representation.
248    //
249    // **NOTE**: String values are case insensitive. Unicode characters are
250    // supported.
251    string string_val = 2;
252
253    // Long representation.
254    int64 long_val = 3;
255
256    // Bool representation.
257    bool bool_val = 4;
258
259    // Double representation.
260    double double_val = 5;
261  }
262}
263
264// Represents an entry in a data source.
265//
266// Each Event has:
267//
268// * A timestamp at which the event occurs.
269// * One or multiple dimensions.
270// * Optionally, a group ID that allows clients to group logically related
271//   events (for example, all events representing payments transactions done by
272//   a user in a day have the same group ID).  If a group ID is not provided, an
273//   internal one will be generated based on the content and `eventTime`.
274//
275// **NOTE**:
276//
277// * Internally, we discretize time in equal-sized chunks and we assume an
278//   event has a 0
279//   [TimeseriesPoint.value][google.cloud.timeseriesinsights.v1.TimeseriesPoint.value]
280//   in a chunk that does not contain any occurrences of an event in the input.
281// * The number of Events with the same group ID should be limited.
282// * Group ID *cannot* be queried.
283// * Group ID does *not* correspond to a user ID or the like. If a user ID is of
284//   interest to be queried, use a user ID `dimension` instead.
285message Event {
286  // Event dimensions.
287  repeated EventDimension dimensions = 1;
288
289  // Event group ID.
290  //
291  // **NOTE**: JSON encoding should use a string to hold a 64-bit integer value,
292  // because a native JSON number holds only 53 binary bits for an integer.
293  int64 group_id = 2;
294
295  // Event timestamp.
296  google.protobuf.Timestamp event_time = 3;
297}
298
299// Appends events to an existing DataSet.
300message AppendEventsRequest {
301  // Events to be appended.
302  //
303  // Note:
304  //
305  // 0. The [DataSet][google.cloud.timeseriesinsights.v1.DataSet] must be shown in a `LOADED` state
306  //    in the results of `list` method; otherwise, all events from
307  //    the append request will be dropped, and a `NOT_FOUND` status will be
308  //    returned.
309  // 0. All events in a single request must have the same
310  //    [groupId][google.cloud.timeseriesinsights.v1.Event.group_id] if set; otherwise, an
311  //    `INVALID_ARGUMENT` status will be returned.
312  // 0. If [groupId][google.cloud.timeseriesinsights.v1.Event.group_id] is not set (or 0), there
313  //    should be only 1 event; otherwise, an `INVALID_ARGUMENT` status will be
314  //    returned.
315  // 0. The events must be newer than the current time minus
316  //    [DataSet TTL][google.cloud.timeseriesinsights.v1.DataSet.ttl] or they will be dropped.
317  repeated Event events = 1;
318
319  // Required. The DataSet to which we want to append to in the format of
320  // "projects/{project}/datasets/{dataset}"
321  string dataset = 2 [
322    (google.api.field_behavior) = REQUIRED,
323    (google.api.resource_reference) = {
324      type: "timeseriesinsights.googleapis.com/Dataset"
325    }
326  ];
327}
328
329// Response for an AppendEvents RPC.
330message AppendEventsResponse {
331  // Dropped events; empty if all events are successfully added.
332  repeated Event dropped_events = 1;
333}
334
335// Create a DataSet request.
336message CreateDataSetRequest {
337  // Required. Client project name which will own this DataSet in the format of
338  // 'projects/{project}'.
339  string parent = 1 [
340    (google.api.field_behavior) = REQUIRED,
341    (google.api.resource_reference) = {
342      type: "cloudresourcemanager.googleapis.com/Project"
343    }
344  ];
345
346  // Required. Dataset to be loaded.
347  DataSet dataset = 2 [(google.api.field_behavior) = REQUIRED];
348}
349
350// Unload DataSet request from the serving system.
351message DeleteDataSetRequest {
352  // Required. Dataset name in the format of "projects/{project}/datasets/{dataset}"
353  string name = 1 [
354    (google.api.field_behavior) = REQUIRED,
355    (google.api.resource_reference) = {
356      type: "timeseriesinsights.googleapis.com/Dataset"
357    }
358  ];
359}
360
361// List the DataSets created by the current project.
362message ListDataSetsRequest {
363  // Required. Project owning the DataSet in the format of "projects/{project}".
364  string parent = 1 [
365    (google.api.field_behavior) = REQUIRED,
366    (google.api.resource_reference) = {
367      type: "cloudresourcemanager.googleapis.com/Project"
368    }
369  ];
370
371  // Number of results to return in the list.
372  int32 page_size = 2;
373
374  // Token to provide to skip to a particular spot in the list.
375  string page_token = 3;
376}
377
378// Created DataSets list response.
379message ListDataSetsResponse {
380  // The list of created DataSets.
381  repeated DataSet datasets = 1;
382
383  // Token to receive the next page of results.
384  string next_page_token = 2;
385}
386
387// A categorical dimension fixed to a certain value.
388message PinnedDimension {
389  // The name of the dimension for which we are fixing its value.
390  string name = 1;
391
392  // Dimension value.
393  //
394  // **NOTE**: The `value` type must match that in the data with the same
395  // `dimension` as name.
396  oneof value {
397    // A string value. This can be used for [dimensions][google.cloud.timeseriesinsights.v1.EventDimension], which
398    // have their value field set to [string_val][google.cloud.timeseriesinsights.v1.EventDimension.string_val].
399    string string_val = 2;
400
401    // A bool value. This can be used for [dimensions][google.cloud.timeseriesinsights.v1.EventDimension], which
402    // have their value field set to [bool_val][google.cloud.timeseriesinsights.v1.EventDimension.bool_val].
403    bool bool_val = 3;
404  }
405}
406
407// Parameters that control the sensitivity and other options for the time series
408// forecast.
409message ForecastParams {
410  // A time period of a fixed interval.
411  enum Period {
412    // Unknown or simply not given.
413    PERIOD_UNSPECIFIED = 0;
414
415    // 1 hour
416    HOURLY = 5;
417
418    // 24 hours
419    DAILY = 1;
420
421    // 7 days
422    WEEKLY = 2;
423
424    // 30 days
425    MONTHLY = 3;
426
427    // 365 days
428    YEARLY = 4;
429  }
430
431  // Optional. Penalize variations between the actual and forecasted values smaller than
432  // this. For more information about how this parameter affects the score, see
433  // the [anomalyScore](EvaluatedSlice.anomaly_score) formula.
434  //
435  // Intuitively, anomaly scores summarize how statistically significant the
436  // change between the actual and forecasted value is compared with what we
437  // expect the change to be (see
438  // [expectedDeviation](EvaluatedSlice.expected_deviation)). However, in
439  // practice, depending on the application, changes smaller than certain
440  // absolute values, while statistically significant, may not be important.
441  //
442  // This parameter allows us to penalize such low absolute value changes.
443  //
444  // Must be in the (0.0, inf) range.
445  //
446  // If unspecified, it defaults to 0.000001.
447  optional double noise_threshold = 12 [(google.api.field_behavior) = OPTIONAL];
448
449  // Optional. Specifying any known seasonality/periodicity in the time series
450  // for the slices we will analyze can improve the quality of the results.
451  //
452  // If unsure, simply leave it unspecified by not setting a value for this
453  // field.
454  //
455  // If your time series has multiple seasonal patterns, then set it to the most
456  // granular one (e.g. if it has daily and weekly patterns, set this to DAILY).
457  Period seasonality_hint = 10 [(google.api.field_behavior) = OPTIONAL];
458
459  // Optional. The length of the returned [forecasted
460  // timeseries][EvaluatedSlice.forecast].
461  //
462  // This duration is currently capped at 100 x
463  // [granularity][google.cloud.timeseriesinsights.v1.TimeseriesParams.granularity].
464  //
465  // Example: If the detection point is set to "2020-12-27T00:00:00Z", the
466  // [granularity][google.cloud.timeseriesinsights.v1.TimeseriesParams.granularity] to "3600s" and the
467  // horizon_duration to "10800s", then we will generate 3 time
468  // series points (from "2020-12-27T01:00:00Z" to "2020-12-27T04:00:00Z"), for
469  // which we will return their forecasted values.
470  //
471  // Note: The horizon time is only used for forecasting not for anormaly
472  // detection. To detect anomalies for multiple points of time,
473  // simply send multiple queries with those as
474  // [detectionTime][google.cloud.timeseriesinsights.v1.QueryDataSetRequest.detection_time].
475  google.protobuf.Duration horizon_duration = 13 [(google.api.field_behavior) = OPTIONAL];
476}
477
478// A point in a time series.
479message TimeseriesPoint {
480  // The timestamp of this point.
481  google.protobuf.Timestamp time = 1;
482
483  // The value for this point.
484  //
485  // It is computed by aggregating all events in the associated slice that are
486  // in the `[time, time + granularity]` range (see
487  // [granularity][google.cloud.timeseriesinsights.v1.TimeseriesParams.granularity]) using the specified
488  // [metric][google.cloud.timeseriesinsights.v1.TimeseriesParams.metric].
489  optional double value = 2;
490}
491
492// A time series.
493message Timeseries {
494  // The points in this time series, ordered by their timestamp.
495  repeated TimeseriesPoint point = 1;
496}
497
498// Forecast result for a given slice.
499message EvaluatedSlice {
500  // Values for all categorical dimensions that uniquely identify this slice.
501  repeated PinnedDimension dimensions = 1;
502
503  // The actual value at the detection time (see
504  // [detectionTime][google.cloud.timeseriesinsights.v1.QueryDataSetRequest.detection_time]).
505  //
506  // **NOTE**: This value can be an estimate, so it should not be used as a
507  // source of truth.
508  optional double detection_point_actual = 11;
509
510  // The expected value at the detection time, which is obtained by forecasting
511  // on the historical time series.
512  optional double detection_point_forecast = 12;
513
514  // How much our forecast model expects the detection point actual will
515  // deviate from its forecasted value based on how well it fit the input time
516  // series.
517  //
518  // In general, we expect the `detectionPointActual` to
519  // be in the `[detectionPointForecast - expectedDeviation,
520  // detectionPointForecast + expectedDeviation]` range. The more the actual
521  // value is outside this range, the more statistically significant the
522  // anomaly is.
523  //
524  // The expected deviation is always positive.
525  optional double expected_deviation = 16;
526
527  // Summarizes how significant the change between the actual and forecasted
528  // detection points are compared with the historical patterns observed on the
529  // [history][google.cloud.timeseriesinsights.v1.EvaluatedSlice.history] time series.
530  //
531  // Defined as *|a - f| / (e + nt)*, where:
532  //
533  // - *a* is the [detectionPointActual][google.cloud.timeseriesinsights.v1.EvaluatedSlice.detection_point_actual].
534  // - *f* is the [detectionPointForecast][google.cloud.timeseriesinsights.v1.EvaluatedSlice.detection_point_forecast].
535  // - *e* is the [expectedDeviation][google.cloud.timeseriesinsights.v1.EvaluatedSlice.expected_deviation].
536  // - *nt` is the [noiseThreshold][google.cloud.timeseriesinsights.v1.ForecastParams.noise_threshold].
537  //
538  // Anomaly scores between different requests and datasets are comparable. As
539  // a guideline, the risk of a slice being an anomaly based on the anomaly
540  // score is:
541  //
542  // - **Very High** if `anomalyScore` > 5.
543  // - **High** if the `anomalyScore` is in the [2, 5] range.
544  // - **Medium** if the `anomalyScore` is in the [1, 2) range.
545  // - **Low** if the `anomalyScore` is < 1.
546  //
547  // If there were issues evaluating this slice, then the anomaly score will be
548  // set to -1.0 and the [status][google.cloud.timeseriesinsights.v1.EvaluatedSlice.status] field will contain details on what
549  // went wrong.
550  optional double anomaly_score = 17;
551
552  // The actual values in the `[`
553  // [detectionTime][google.cloud.timeseriesinsights.v1.QueryDataSetRequest.detection_time] `-`
554  // [forecastHistory][google.cloud.timeseriesinsights.v1.TimeseriesParams.forecast_history]`,`
555  // [detectionTime][google.cloud.timeseriesinsights.v1.QueryDataSetRequest.detection_time] `]` time
556  // range.
557  //
558  // **NOTE**: This field is only populated if
559  // [returnTimeseries][google.cloud.timeseriesinsights.v1.QueryDataSetRequest.return_timeseries] is true.
560  Timeseries history = 5;
561
562  // The forecasted values in the `[`
563  // [detectionTime][google.cloud.timeseriesinsights.v1.QueryDataSetRequest.detection_time] `+`
564  // [granularity][google.cloud.timeseriesinsights.v1.TimeseriesParams.granularity]`,`
565  // [forecastParams.horizonTime][google.cloud.timeseriesinsights.v1.QueryDataSetRequest.forecast_params] `]` time
566  // range.
567  //
568  // **NOTE**: This field is only populated if
569  // [returnTimeseries][google.cloud.timeseriesinsights.v1.QueryDataSetRequest.return_timeseries] is true.
570  Timeseries forecast = 10;
571
572  // Evaluation status. Contains an error message if the `anomalyScore` is < 0.
573  //
574  // Possible error messages:
575  //
576  // - **"Time series too sparse"**: The returned time series for this slice did
577  // not contain enough data points (we require a minimum of 10).
578  // - **"Not enough recent time series points"**: The time series contains the
579  // minimum of 10 points, but there are not enough close in time to the
580  // detection point.
581  // - **"Missing detection point data"**: There were not events to be
582  // aggregated within the `[detectionTime, detectionTime + granularity]` time
583  // interval, so we don't have an actual value with which we can compare our
584  // prediction.
585  // - **"Data retrieval error"**: We failed to retrieve the time series data
586  // for this slice and could not evaluate it successfully. Should be a
587  // transient error.
588  // - **"Internal server error"**: Internal unexpected error.
589  google.rpc.Status status = 18;
590}
591
592// Parameters that control how we slice the dataset and, optionally, filter
593// slices that have some specific values on some dimensions (pinned dimensions).
594message SlicingParams {
595  // Required. Dimensions over which we will group the events in slices. The names
596  // specified here come from the
597  // [EventDimension.name][google.cloud.timeseriesinsights.v1.EventDimension.name] field. At least
598  // one dimension name must be specified. All dimension names that do not exist
599  // in the queried `DataSet` will be ignored.
600  //
601  // Currently only dimensions that hold string values can be specified here.
602  repeated string dimension_names = 1 [(google.api.field_behavior) = REQUIRED];
603
604  // Optional. We will only analyze slices for which
605  // [EvaluatedSlice.dimensions][google.cloud.timeseriesinsights.v1.EvaluatedSlice.dimensions] contain all of the
606  // following pinned dimensions. A query with a pinned dimension `{ name: "d3"
607  // stringVal: "v3" }` will only analyze events which contain the dimension `{
608  // name: "d3" stringVal: "v3" }`.
609  // The [pinnedDimensions][google.cloud.timeseriesinsights.v1.SlicingParams.pinned_dimensions] and
610  // [dimensionNames][google.cloud.timeseriesinsights.v1.SlicingParams.dimension_names] fields can **not**
611  // share the same dimension names.
612  //
613  // Example a valid specification:
614  //
615  // ```json
616  // {
617  //   dimensionNames: ["d1", "d2"],
618  //   pinnedDimensions: [
619  //     { name: "d3" stringVal: "v3" },
620  //     { name: "d4" stringVal: "v4" }
621  //   ]
622  // }
623  // ```
624  //
625  // In the previous example we will slice the dataset by dimensions "d1",
626  // "d2", "d3" and "d4", but we will only analyze slices for which "d3=v3" and
627  // "d4=v4".
628  //
629  // The following example is **invalid** as "d2" is present in both
630  // dimensionNames and pinnedDimensions:
631  //
632  // ```json
633  // {
634  //   dimensionNames: ["d1", "d2"],
635  //   pinnedDimensions: [
636  //     { name: "d2" stringVal: "v2" },
637  //     { name: "d4" stringVal: "v4" }
638  //   ]
639  // }
640  // ```
641  repeated PinnedDimension pinned_dimensions = 2 [(google.api.field_behavior) = OPTIONAL];
642}
643
644// Parameters that control how we construct the time series for each slice.
645message TimeseriesParams {
646  // Methods by which we can aggregate multiple events by a given
647  // [metric][google.cloud.timeseriesinsights.v1.TimeseriesParams.metric].
648  enum AggregationMethod {
649    // Unspecified.
650    AGGREGATION_METHOD_UNSPECIFIED = 0;
651
652    // Aggregate multiple events by summing up the values found in the
653    // [metric][google.cloud.timeseriesinsights.v1.TimeseriesParams.metric] dimension.
654    SUM = 1;
655
656    // Aggregate multiple events by averaging out the values found in the
657    // [metric][google.cloud.timeseriesinsights.v1.TimeseriesParams.metric] dimension.
658    AVERAGE = 2;
659  }
660
661  // Required. How long should we go in the past when fetching the timeline used for
662  // forecasting each slice.
663  //
664  // This is used in combination with the
665  // [detectionTime][google.cloud.timeseriesinsights.v1.QueryDataSetRequest.detection_time] parameter.
666  // The time series we construct will have the following time range:
667  // `[detectionTime - forecastHistory, detectionTime + granularity]`.
668  //
669  // The forecast history might be rounded up, so that a multiple of
670  // `granularity` is used to process the query.
671  //
672  // Note: If there are not enough events in the
673  // `[detectionTime - forecastHistory, detectionTime + granularity]` time
674  // interval, the slice evaluation can fail. For more information, see
675  // [EvaluatedSlice.status][google.cloud.timeseriesinsights.v1.EvaluatedSlice.status].
676  google.protobuf.Duration forecast_history = 1 [(google.api.field_behavior) = REQUIRED];
677
678  // Required. The time granularity of the time series (on the x-axis). Each time series
679  // point starting at time T will aggregate all events for a particular slice
680  // in *[T, T + granularity)* time windows.
681  //
682  // Note: The aggregation is decided based on the
683  // [metric][google.cloud.timeseriesinsights.v1.TimeseriesParams.metric] parameter.
684  //
685  // This granularity defines the query-time aggregation windows and is not
686  // necessarily related to any event time granularity in the raw data (though
687  // we do recommend that the query-time granularity is not finer than the
688  // ingestion-time one).
689  //
690  // Currently, the minimal supported granularity is 10 seconds.
691  google.protobuf.Duration granularity = 2 [(google.api.field_behavior) = REQUIRED];
692
693  // Optional. Denotes the [name][google.cloud.timeseriesinsights.v1.EventDimension.name] of a numerical
694  // dimension that will have its values aggregated to compute the y-axis of the
695  // time series.
696  //
697  // The aggregation method must also be specified by setting the
698  // [metricAggregationMethod][google.cloud.timeseriesinsights.v1.TimeseriesParams.metric_aggregation_method]
699  // field.
700  //
701  // Note: Currently, if the aggregation method is unspecified, we will
702  // default to SUM for backward compatibility reasons, but new implementations
703  // should set the
704  // [metricAggregationMethod][google.cloud.timeseriesinsights.v1.TimeseriesParams.metric_aggregation_method]
705  // explicitly.
706  //
707  // If the metric is unspecified, we will use the number of events that each
708  // time series point contains as the point value.
709  //
710  // Example: Let's assume we have the following three events in our dataset:
711  // ```json
712  // {
713  //   eventTime: "2020-12-27T00:00:00Z",
714  //   dimensions: [
715  //     { name: "d1" stringVal: "v1" },
716  //     { name: "d2" stringVal: "v2" }
717  //     { name: "m1" longVal: 100 }
718  //     { name: "m2" longVal: 11 }
719  //   ]
720  // },
721  // {
722  //   eventTime: "2020-12-27T00:10:00Z",
723  //   dimensions: [
724  //     { name: "d1" stringVal: "v1" },
725  //     { name: "d2" stringVal: "v2" }
726  //     { name: "m1" longVal: 200 }
727  //     { name: "m2" longVal: 22 }
728  //   ]
729  // },
730  // {
731  //   eventTime: "2020-12-27T00:20:00Z",
732  //   dimensions: [
733  //     { name: "d1" stringVal: "v1" },
734  //     { name: "d2" stringVal: "v2" }
735  //     { name: "m1" longVal: 300 }
736  //     { name: "m2" longVal: 33 }
737  //   ]
738  // }
739  // ```
740  //
741  // These events are all within the same hour, spaced 10 minutes between each
742  // of them. Assuming our [QueryDataSetRequest][google.cloud.timeseriesinsights.v1.QueryDataSetRequest] had set
743  // [slicingParams.dimensionNames][google.cloud.timeseriesinsights.v1.SlicingParams.dimension_names] to ["d1",
744  // "d2"] and [timeseries_params.granularity][google.cloud.timeseriesinsights.v1.TimeseriesParams.granularity] to
745  // "3600s", then all the previous events will be aggregated into the same
746  // [timeseries point][google.cloud.timeseriesinsights.v1.TimeseriesPoint].
747  //
748  // The time series point that they're all part of will have the
749  // [time][google.cloud.timeseriesinsights.v1.TimeseriesPoint.time] set to "2020-12-27T00:00:00Z" and the
750  // [value][google.cloud.timeseriesinsights.v1.TimeseriesPoint.value] populated based on this metric field:
751  //
752  // - If the metric is set to "m1" and metric_aggregation_method to SUM, then
753  // the value of the point will be 600.
754  // - If the metric is set to "m2" and metric_aggregation_method to SUM, then
755  // the value of the point will be 66.
756  // - If the metric is set to "m1" and metric_aggregation_method to AVERAGE,
757  // then the value of the point will be 200.
758  // - If the metric is set to "m2" and metric_aggregation_method to AVERAGE,
759  // then the value of the point will be 22.
760  // - If the metric field is "" or unspecified, then the value of the point
761  // will be 3, as we will simply count the events.
762  optional string metric = 4 [(google.api.field_behavior) = OPTIONAL];
763
764  // Optional. Together with the [metric][google.cloud.timeseriesinsights.v1.TimeseriesParams.metric] field, specifies how
765  // we will aggregate multiple events to obtain the value of a time series
766  // point. See the [metric][google.cloud.timeseriesinsights.v1.TimeseriesParams.metric] documentation for more
767  // details.
768  //
769  // If the metric is not specified or "", then this field will be ignored.
770  AggregationMethod metric_aggregation_method = 5 [(google.api.field_behavior) = OPTIONAL];
771}
772
773// Request for performing a query against a loaded DataSet.
774message QueryDataSetRequest {
775  // Required. Loaded DataSet to be queried in the format of
776  // "projects/{project}/datasets/{dataset}"
777  string name = 1 [
778    (google.api.field_behavior) = REQUIRED,
779    (google.api.resource_reference) = {
780      type: "timeseriesinsights.googleapis.com/Dataset"
781    }
782  ];
783
784  // Required. This is the point in time that we want to probe for anomalies.
785  //
786  // The corresponding [TimeseriesPoint][google.cloud.timeseriesinsights.v1.TimeseriesPoint] is referred to as the
787  // detection point.
788  //
789  // **NOTE**: As with any other time series point, the value is given by
790  // aggregating all events in the slice that are in the
791  // [detectionTime, detectionTime + granularity) time interval, where
792  // the granularity is specified in the
793  // [timeseriesParams.granularity][google.cloud.timeseriesinsights.v1.TimeseriesParams.granularity] field.
794  google.protobuf.Timestamp detection_time = 11 [(google.api.field_behavior) = REQUIRED];
795
796  // How many slices are returned in
797  // [QueryDataSetResponse.slices][google.cloud.timeseriesinsights.v1.QueryDataSetResponse.slices].
798  //
799  // The returned slices are tentatively the ones with the highest
800  // [anomaly scores][google.cloud.timeseriesinsights.v1.EvaluatedSlice.anomaly_score] in the dataset that match
801  // the query, but it is not guaranteed.
802  //
803  // Reducing this number will improve query performance, both in terms of
804  // latency and resource usage.
805  //
806  // Defaults to 50.
807  optional int32 num_returned_slices = 13;
808
809  // Parameters controlling how we will split the dataset into the slices that
810  // we will analyze.
811  SlicingParams slicing_params = 9;
812
813  // Parameters controlling how we will build the time series used to predict
814  // the [detectionTime][google.cloud.timeseriesinsights.v1.QueryDataSetRequest.detection_time] value for each slice.
815  TimeseriesParams timeseries_params = 10;
816
817  // Parameters that control the time series forecasting models, such as the
818  // sensitivity of the anomaly detection.
819  ForecastParams forecast_params = 5;
820
821  // If specified, we will return the actual and forecasted time for all
822  // returned slices.
823  //
824  // The time series are returned in the
825  // [EvaluatedSlice.history][google.cloud.timeseriesinsights.v1.EvaluatedSlice.history] and
826  // [EvaluatedSlice.forecast][google.cloud.timeseriesinsights.v1.EvaluatedSlice.forecast] fields.
827  bool return_timeseries = 8;
828}
829
830// Response for a query executed by the system.
831message QueryDataSetResponse {
832  // Loaded DataSet that was queried.
833  string name = 1;
834
835  // Slices sorted in descending order by their
836  // [anomalyScore][google.cloud.timeseriesinsights.v1.EvaluatedSlice.anomaly_score].
837  //
838  // At most [numReturnedSlices][google.cloud.timeseriesinsights.v1.QueryDataSetRequest.num_returned_slices]
839  // slices are present in this field.
840  repeated EvaluatedSlice slices = 3;
841}
842
843// Request for evaluateSlice.
844message EvaluateSliceRequest {
845  // Required. Loaded DataSet to be queried in the format of
846  // "projects/{project}/datasets/{dataset}"
847  string dataset = 1 [
848    (google.api.field_behavior) = REQUIRED,
849    (google.api.resource_reference) = {
850      type: "timeseriesinsights.googleapis.com/Dataset"
851    }
852  ];
853
854  // Required. Dimensions with pinned values that specify the slice for which we will
855  // fetch the time series.
856  repeated PinnedDimension pinned_dimensions = 2 [(google.api.field_behavior) = REQUIRED];
857
858  // Required. This is the point in time that we want to probe for anomalies.
859  //
860  // See documentation for
861  // [QueryDataSetRequest.detectionTime][google.cloud.timeseriesinsights.v1.QueryDataSetRequest.detection_time].
862  google.protobuf.Timestamp detection_time = 3 [(google.api.field_behavior) = REQUIRED];
863
864  // Parameters controlling how we will build the time series used to predict
865  // the [detectionTime][google.cloud.timeseriesinsights.v1.EvaluateSliceRequest.detection_time] value for this slice.
866  TimeseriesParams timeseries_params = 4;
867
868  // Parameters that control the time series forecasting models, such as the
869  // sensitivity of the anomaly detection.
870  ForecastParams forecast_params = 5;
871}
872
873// Request for evaluateTimeseries.
874message EvaluateTimeseriesRequest {
875  // Required. Client project name in the format of 'projects/{project}'.
876  string parent = 1 [
877    (google.api.field_behavior) = REQUIRED,
878    (google.api.resource_reference) = {
879      type: "cloudresourcemanager.googleapis.com/Project"
880    }
881  ];
882
883  // Evaluate this time series without requiring it was previously loaded in
884  // a data set.
885  //
886  // The evaluated time series point is the last one, analogous to calling
887  // evaluateSlice or query with
888  // [detectionTime][google.cloud.timeseriesinsights.v1.EvaluateSliceRequest.detection_time] set to
889  // `timeseries.point(timeseries.point_size() - 1).time`.
890  //
891  // The length of the time series must be at least 10.
892  //
893  // All points must have the same time offset relative to the granularity. For
894  // example, if the [granularity][google.cloud.timeseriesinsights.v1.EvaluateTimeseriesRequest.granularity] is "5s", then the following
895  // point.time sequences are valid:
896  // - "100s", "105s", "120s", "125s" (no offset)
897  // - "102s", "107s", "122s", "127s" (offset is "2s")
898  // However, the following sequence is invalid as it has inconsistent offsets:
899  // - "100s", "105s", "122s", "127s" (offsets are either "0s" or "2s")
900  Timeseries timeseries = 2;
901
902  // The granularity of the time series (time distance between two consecutive
903  // points).
904  google.protobuf.Duration granularity = 3;
905
906  // The forecast parameters.
907  ForecastParams forecast_params = 4;
908}
909