// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

syntax = "proto3";

package google.devtools.cloudprofiler.v2;

import "google/api/annotations.proto";
import "google/protobuf/duration.proto";
import "google/protobuf/field_mask.proto";
import "google/api/client.proto";

option csharp_namespace = "Google.Cloud.Profiler.V2";
option go_package = "google.golang.org/genproto/googleapis/devtools/cloudprofiler/v2;cloudprofiler";
option java_multiple_files = true;
option java_outer_classname = "ProfilerProto";
option java_package = "com.google.devtools.cloudprofiler.v2";
option php_namespace = "Google\\Cloud\\Profiler\\V2";
option ruby_package = "Google::Cloud::Profiler::V2";

// Manage the collection of continuous profiling data provided by profiling
// agents running in the cloud or by an offline provider of profiling data.
//
// General guidelines:
// * Profiles for a single deployment must be created in ascending time order.
// * Profiles can be created in either online or offline mode, see below.
service ProfilerService {
  option (google.api.default_host) = "cloudprofiler.googleapis.com";
  option (google.api.oauth_scopes) =
      "https://www.googleapis.com/auth/cloud-platform,"
      "https://www.googleapis.com/auth/monitoring,"
      "https://www.googleapis.com/auth/monitoring.write";

  // CreateProfile creates a new profile resource in the online mode.
  //
  // The server ensures that the new profiles are created at a constant rate per
  // deployment, so the creation request may hang for some time until the next
  // profile session is available.
  //
  // The request may fail with ABORTED error if the creation is not available
  // within ~1m, the response will indicate the duration of the backoff the
  // client should take before attempting creating a profile again. The backoff
  // duration is returned in google.rpc.RetryInfo extension on the response
  // status. To a gRPC client, the extension will be return as a
  // binary-serialized proto in the trailing metadata item named
  // "google.rpc.retryinfo-bin".
  rpc CreateProfile(CreateProfileRequest) returns (Profile) {
    option (google.api.http) = {
      post: "/v2/{parent=projects/*}/profiles"
      body: "*"
    };
  }

  // CreateOfflineProfile creates a new profile resource in the offline mode.
  // The client provides the profile to create along with the profile bytes, the
  // server records it.
  rpc CreateOfflineProfile(CreateOfflineProfileRequest) returns (Profile) {
    option (google.api.http) = {
      post: "/v2/{parent=projects/*}/profiles:createOffline"
      body: "profile"
    };
  }

  // UpdateProfile updates the profile bytes and labels on the profile resource
  // created in the online mode. Updating the bytes for profiles created in the
  // offline mode is currently not supported: the profile content must be
  // provided at the time of the profile creation.
  rpc UpdateProfile(UpdateProfileRequest) returns (Profile) {
    option (google.api.http) = {
      patch: "/v2/{profile.name=projects/*/profiles/*}"
      body: "profile"
    };
  }
}

// CreateProfileRequest describes a profile resource online creation request.
// The deployment field must be populated. The profile_type specifies the list
// of profile types supported by the agent. The creation call will hang until a
// profile of one of these types needs to be collected.
message CreateProfileRequest {
  // Parent project to create the profile in.
  string parent = 4;

  // Deployment details.
  Deployment deployment = 1;

  // One or more profile types that the agent is capable of providing.
  repeated ProfileType profile_type = 2;
}

// CreateOfflineProfileRequest describes a profile resource offline creation
// request. Profile field must be set.
message CreateOfflineProfileRequest {
  // Parent project to create the profile in.
  string parent = 1;

  // Contents of the profile to create.
  Profile profile = 2;
}

// UpdateProfileRequest contains the profile to update.
message UpdateProfileRequest {
  // Profile to update
  Profile profile = 1;

  // Field mask used to specify the fields to be overwritten. Currently only
  // profile_bytes and labels fields are supported by UpdateProfile, so only
  // those fields can be specified in the mask. When no mask is provided, all
  // fields are overwritten.
  google.protobuf.FieldMask update_mask = 2;
}

// Profile resource.
message Profile {
  // Output only. Opaque, server-assigned, unique ID for this profile.
  string name = 1;

  // Type of profile.
  // For offline mode, this must be specified when creating the profile. For
  // online mode it is assigned and returned by the server.
  ProfileType profile_type = 2;

  // Deployment this profile corresponds to.
  Deployment deployment = 3;

  // Duration of the profiling session.
  // Input (for the offline mode) or output (for the online mode).
  // The field represents requested profiling duration. It may slightly differ
  // from the effective profiling duration, which is recorded in the profile
  // data, in case the profiling can't be stopped immediately (e.g. in case
  // stopping the profiling is handled asynchronously).
  google.protobuf.Duration duration = 4;

  // Input only. Profile bytes, as a gzip compressed serialized proto, the
  // format is https://github.com/google/pprof/blob/master/proto/profile.proto.
  bytes profile_bytes = 5;

  // Input only. Labels associated to this specific profile. These labels will
  // get merged with the deployment labels for the final data set.  See
  // documentation on deployment labels for validation rules and limits.
  map<string, string> labels = 6;
}

// Deployment contains the deployment identification information.
message Deployment {
  // Project ID is the ID of a cloud project.
  // Validation regex: `^[a-z][-a-z0-9:.]{4,61}[a-z0-9]$`.
  string project_id = 1;

  // Target is the service name used to group related deployments:
  // * Service name for GAE Flex / Standard.
  // * Cluster and container name for GKE.
  // * User-specified string for direct GCE profiling (e.g. Java).
  // * Job name for Dataflow.
  // Validation regex: `^[a-z]([-a-z0-9_.]{0,253}[a-z0-9])?$`.
  string target = 2;

  // Labels identify the deployment within the user universe and same target.
  // Validation regex for label names: `^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$`.
  // Value for an individual label must be <= 512 bytes, the total
  // size of all label names and values must be <= 1024 bytes.
  //
  // Label named "language" can be used to record the programming language of
  // the profiled deployment. The standard choices for the value include "java",
  // "go", "python", "ruby", "nodejs", "php", "dotnet".
  //
  // For deployments running on Google Cloud Platform, "zone" or "region" label
  // should be present describing the deployment location. An example of a zone
  // is "us-central1-a", an example of a region is "us-central1" or
  // "us-central".
  map<string, string> labels = 3;
}

// ProfileType is type of profiling data.
// NOTE: the enumeration member names are used (in lowercase) as unique string
// identifiers of profile types, so they must not be renamed.
enum ProfileType {
  // Unspecified profile type.
  PROFILE_TYPE_UNSPECIFIED = 0;

  // Thread CPU time sampling.
  CPU = 1;

  // Wallclock time sampling. More expensive as stops all threads.
  WALL = 2;

  // In-use heap profile. Represents a snapshot of the allocations that are
  // live at the time of the profiling.
  HEAP = 3;

  // Single-shot collection of all thread stacks.
  THREADS = 4;

  // Synchronization contention profile.
  CONTENTION = 5;

  // Peak heap profile.
  PEAK_HEAP = 6;

  // Heap allocation profile. It represents the aggregation of all allocations
  // made over the duration of the profile. All allocations are included,
  // including those that might have been freed by the end of the profiling
  // interval. The profile is in particular useful for garbage collecting
  // languages to understand which parts of the code create most of the garbage
  // collection pressure to see if those can be optimized.
  HEAP_ALLOC = 7;
}
